about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-08-23 10:09:14 +0000
committerAlyssa Ross <hi@alyssa.is>2023-08-26 09:07:03 +0000
commit63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f (patch)
treed58934cb48f9c953b19a0d0d5cffc0d0c5561471 /nixpkgs/nixos
parentc4eef3dacb2a3d359561f30917d9e3cc4e041be9 (diff)
parent91a22f76cd1716f9d0149e8a5c68424bb691de15 (diff)
downloadnixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar.gz
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar.bz2
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar.lz
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar.xz
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.tar.zst
nixlib-63dabcc77ef9a56655e1ca2ab2e25e6163a72c1f.zip
Merge branch 'nixos-unstable' of https://github.com/NixOS/nixpkgs
Conflicts:
	nixpkgs/pkgs/build-support/go/module.nix
	nixpkgs/pkgs/development/python-modules/django-mailman3/default.nix
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/README5
-rw-r--r--nixpkgs/nixos/README.md86
-rw-r--r--nixpkgs/nixos/doc/manual/administration/service-mgmt.chapter.md30
-rw-r--r--nixpkgs/nixos/doc/manual/contributing-to-this-manual.chapter.md92
-rw-r--r--nixpkgs/nixos/doc/manual/default.nix6
-rw-r--r--nixpkgs/nixos/doc/manual/manpages/README.md57
-rw-r--r--nixpkgs/nixos/doc/manual/manpages/nixos-option.889
-rw-r--r--nixpkgs/nixos/doc/manual/manpages/nixos-rebuild.8452
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md41
-rw-r--r--nixpkgs/nixos/lib/make-squashfs.nix4
-rwxr-xr-xnixpkgs/nixos/lib/test-driver/test_driver/__init__.py8
-rw-r--r--nixpkgs/nixos/modules/config/malloc.nix1
-rw-r--r--nixpkgs/nixos/modules/config/no-x-libs.nix17
-rw-r--r--nixpkgs/nixos/modules/hardware/video/nvidia.nix782
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix59
-rw-r--r--nixpkgs/nixos/modules/image/repart.nix13
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix6
-rw-r--r--nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8 (renamed from nixpkgs/nixos/doc/manual/manpages/nixos-build-vms.8)0
-rw-r--r--nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8 (renamed from nixpkgs/nixos/doc/manual/manpages/nixos-enter.8)0
-rw-r--r--nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8 (renamed from nixpkgs/nixos/doc/manual/manpages/nixos-generate-config.8)0
-rw-r--r--nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8 (renamed from nixpkgs/nixos/doc/manual/manpages/nixos-install.8)0
-rw-r--r--nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8 (renamed from nixpkgs/nixos/doc/manual/manpages/nixos-version.8)0
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix10
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix11
-rw-r--r--nixpkgs/nixos/modules/misc/documentation.nix2
-rw-r--r--nixpkgs/nixos/modules/module-list.nix5
-rw-r--r--nixpkgs/nixos/modules/profiles/installation-device.nix3
-rw-r--r--nixpkgs/nixos/modules/programs/captive-browser.nix32
-rw-r--r--nixpkgs/nixos/modules/programs/environment.nix7
-rw-r--r--nixpkgs/nixos/modules/programs/firefox.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/fish.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/gamescope.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/htop.nix3
-rw-r--r--nixpkgs/nixos/modules/programs/hyprland.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/steam.nix4
-rw-r--r--nixpkgs/nixos/modules/security/ipa.nix2
-rw-r--r--nixpkgs/nixos/modules/security/pam.nix14
-rw-r--r--nixpkgs/nixos/modules/security/wrappers/wrapper.c40
-rw-r--r--nixpkgs/nixos/modules/services/audio/goxlr-utility.nix48
-rw-r--r--nixpkgs/nixos/modules/services/audio/liquidsoap.nix1
-rw-r--r--nixpkgs/nixos/modules/services/cluster/patroni/default.nix2
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix26
-rw-r--r--nixpkgs/nixos/modules/services/databases/influxdb2.nix124
-rw-r--r--nixpkgs/nixos/modules/services/games/openarena.nix6
-rw-r--r--nixpkgs/nixos/modules/services/games/quake3-server.nix10
-rw-r--r--nixpkgs/nixos/modules/services/hardware/keyd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/logging/graylog.nix4
-rw-r--r--nixpkgs/nixos/modules/services/mail/maddy.nix8
-rw-r--r--nixpkgs/nixos/modules/services/matrix/conduit.nix10
-rw-r--r--nixpkgs/nixos/modules/services/matrix/synapse.md8
-rw-r--r--nixpkgs/nixos/modules/services/matrix/synapse.nix87
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitea.nix1
-rw-r--r--nixpkgs/nixos/modules/services/misc/zoneminder.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix14
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/netdata.nix1
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix16
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix69
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/eris-server.nix103
-rw-r--r--nixpkgs/nixos/modules/services/networking/dae.nix41
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix21
-rw-r--r--nixpkgs/nixos/modules/services/networking/haproxy.nix17
-rw-r--r--nixpkgs/nixos/modules/services/networking/headscale.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/hostapd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/jool.nix222
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/chrony.nix14
-rw-r--r--nixpkgs/nixos/modules/services/networking/zerotierone.nix4
-rw-r--r--nixpkgs/nixos/modules/services/security/kanidm.nix14
-rw-r--r--nixpkgs/nixos/modules/services/security/oauth2_proxy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/opensnitch.nix14
-rw-r--r--nixpkgs/nixos/modules/services/tracing/tempo.nix14
-rw-r--r--nixpkgs/nixos/modules/services/video/mediamtx.nix53
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.nix8
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/invidious.nix64
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/lemmy.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix6
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/photoprism.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/minio.nix6
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/rustus.nix4
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix9
-rw-r--r--nixpkgs/nixos/modules/services/x11/picom.nix6
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix2
-rwxr-xr-xnixpkgs/nixos/modules/system/activation/switch-to-configuration.pl58
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix32
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel.nix32
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix58
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl32
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix49
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix21
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/libvirtd.nix71
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxd-agent.nix91
-rw-r--r--nixpkgs/nixos/release.nix2
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix10
-rw-r--r--nixpkgs/nixos/tests/budgie.nix6
-rw-r--r--nixpkgs/nixos/tests/caddy.nix44
-rw-r--r--nixpkgs/nixos/tests/chrony.nix31
-rw-r--r--nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix14
-rw-r--r--nixpkgs/nixos/tests/eris-server.nix23
-rw-r--r--nixpkgs/nixos/tests/fcitx5/config11
-rw-r--r--nixpkgs/nixos/tests/fcitx5/default.nix47
-rw-r--r--nixpkgs/nixos/tests/fcitx5/profile27
-rw-r--r--nixpkgs/nixos/tests/influxdb2.nix36
-rw-r--r--nixpkgs/nixos/tests/jool.nix250
-rw-r--r--nixpkgs/nixos/tests/kernel-generic.nix6
-rw-r--r--nixpkgs/nixos/tests/libvirtd.nix7
-rw-r--r--nixpkgs/nixos/tests/matrix/synapse.nix15
-rw-r--r--nixpkgs/nixos/tests/mediamtx.nix57
-rw-r--r--nixpkgs/nixos/tests/netdata.nix5
-rw-r--r--nixpkgs/nixos/tests/nextcloud/basic.nix4
-rw-r--r--nixpkgs/nixos/tests/nextcloud/openssl-sse.nix4
-rw-r--r--nixpkgs/nixos/tests/nixops/default.nix9
-rw-r--r--nixpkgs/nixos/tests/opensnitch.nix62
-rw-r--r--nixpkgs/nixos/tests/pantheon.nix3
-rw-r--r--nixpkgs/nixos/tests/prometheus-exporters.nix19
-rw-r--r--nixpkgs/nixos/tests/switch-test.nix162
-rw-r--r--nixpkgs/nixos/tests/systemd-boot.nix10
-rw-r--r--nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix2
-rw-r--r--nixpkgs/nixos/tests/web-servers/agate.nix2
-rw-r--r--nixpkgs/nixos/tests/wrappers.nix21
122 files changed, 2854 insertions, 1495 deletions
diff --git a/nixpkgs/nixos/README b/nixpkgs/nixos/README
deleted file mode 100644
index ce4dd1988d2d..000000000000
--- a/nixpkgs/nixos/README
+++ /dev/null
@@ -1,5 +0,0 @@
-*** NixOS ***
-
-NixOS is a Linux distribution based on the purely functional package
-management system Nix.  More information can be found at
-https://nixos.org/nixos and in the manual in doc/manual.
diff --git a/nixpkgs/nixos/README.md b/nixpkgs/nixos/README.md
new file mode 100644
index 000000000000..b3cd9d234fa6
--- /dev/null
+++ b/nixpkgs/nixos/README.md
@@ -0,0 +1,86 @@
+# NixOS
+
+NixOS is a Linux distribution based on the purely functional package
+management system Nix.  More information can be found at
+https://nixos.org/nixos and in the manual in doc/manual.
+
+## Testing changes
+
+You can add new module to your NixOS configuration file (usually it’s `/etc/nixos/configuration.nix`). And do `sudo nixos-rebuild test -I nixpkgs=<path to your local nixpkgs folder> --fast`.
+
+## Reviewing contributions
+
+When changing the bootloader installation process, extra care must be taken. Grub installations cannot be rolled back, hence changes may break people’s installations forever. For any non-trivial change to the bootloader please file a PR asking for review, especially from \@edolstra.
+
+### Module updates
+
+Module updates are submissions changing modules in some ways. These often contains changes to the options or introduce new options.
+
+Reviewing process:
+
+- Ensure that the module maintainers are notified.
+  - [CODEOWNERS](https://help.github.com/articles/about-codeowners/) will make GitHub notify users based on the submitted changes, but it can happen that it misses some of the package maintainers.
+- Ensure that the module tests, if any, are succeeding.
+- Ensure that the introduced options are correct.
+  - Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
+  - Description, default and example should be provided.
+- Ensure that option changes are backward compatible.
+  - `mkRenamedOptionModuleWith` provides a way to make option changes backward compatible.
+- Ensure that removed options are declared with `mkRemovedOptionModule`
+- Ensure that changes that are not backward compatible are mentioned in release notes.
+- Ensure that documentations affected by the change is updated.
+
+Sample template for a module update review is provided below.
+
+```markdown
+##### Reviewed points
+
+- [ ] changes are backward compatible
+- [ ] removed options are declared with `mkRemovedOptionModule`
+- [ ] changes that are not backward compatible are documented in release notes
+- [ ] module tests succeed on ARCHITECTURE
+- [ ] options types are appropriate
+- [ ] options description is set
+- [ ] options example is provided
+- [ ] documentation affected by the changes is updated
+
+##### Possible improvements
+
+##### Comments
+```
+
+### New modules
+
+New modules submissions introduce a new module to NixOS.
+
+Reviewing process:
+
+- Ensure that the module tests, if any, are succeeding.
+- Ensure that the introduced options are correct.
+  - Type should be appropriate (string related types differs in their merging capabilities, `loaOf` and `string` types are deprecated).
+  - Description, default and example should be provided.
+- Ensure that module `meta` field is present
+  - Maintainers should be declared in `meta.maintainers`.
+  - Module documentation should be declared with `meta.doc`.
+- Ensure that the module respect other modules functionality.
+  - For example, enabling a module should not open firewall ports by default.
+
+Sample template for a new module review is provided below.
+
+```markdown
+##### Reviewed points
+
+- [ ] module path fits the guidelines
+- [ ] module tests succeed on ARCHITECTURE
+- [ ] options have appropriate types
+- [ ] options have default
+- [ ] options have example
+- [ ] options have descriptions
+- [ ] No unneeded package is added to environment.systemPackages
+- [ ] meta.maintainers is set
+- [ ] module documentation is declared in meta.doc
+
+##### Possible improvements
+
+##### Comments
+```
diff --git a/nixpkgs/nixos/doc/manual/administration/service-mgmt.chapter.md b/nixpkgs/nixos/doc/manual/administration/service-mgmt.chapter.md
index 674c73741680..bc9bdbe3708b 100644
--- a/nixpkgs/nixos/doc/manual/administration/service-mgmt.chapter.md
+++ b/nixpkgs/nixos/doc/manual/administration/service-mgmt.chapter.md
@@ -118,3 +118,33 @@ the symlink, and this path is in `/nix/store/.../lib/systemd/user/`.
 Hence [garbage collection](#sec-nix-gc) will remove that file and you
 will wind up with a broken symlink in your systemd configuration, which
 in turn will not make the service / timer start on login.
+
+## Template units {#sect-nixos-systemd-template-units}
+
+systemd supports templated units where a base unit can be started multiple
+times with a different parameter. The syntax to accomplish this is
+`service-name@instance-name.service`. Units get the instance name passed to
+them (see `systemd.unit(5)`). NixOS has support for these kinds of units and
+for template-specific overrides. A service needs to be defined twice, once
+for the base unit and once for the instance. All instances must include
+`overrideStrategy = "asDropin"` for the change detection to work. This
+example illustrates this:
+```nix
+{
+  systemd.services = {
+    "base-unit@".serviceConfig = {
+      ExecStart = "...";
+      User = "...";
+    };
+    "base-unit@instance-a" = {
+      overrideStrategy = "asDropin"; # needed for templates to work
+      wantedBy = [ "multi-user.target" ]; # causes NixOS to manage the instance
+    };
+    "base-unit@instance-b" = {
+      overrideStrategy = "asDropin"; # needed for templates to work
+      wantedBy = [ "multi-user.target" ]; # causes NixOS to manage the instance
+      serviceConfig.User = "root"; # also override something for this specific instance
+    };
+  };
+}
+```
diff --git a/nixpkgs/nixos/doc/manual/contributing-to-this-manual.chapter.md b/nixpkgs/nixos/doc/manual/contributing-to-this-manual.chapter.md
index 4633c7e1b058..6245280e30f0 100644
--- a/nixpkgs/nixos/doc/manual/contributing-to-this-manual.chapter.md
+++ b/nixpkgs/nixos/doc/manual/contributing-to-this-manual.chapter.md
@@ -1,11 +1,13 @@
 # Contributing to this manual {#chap-contributing}
 
 The [DocBook] and CommonMark sources of the NixOS manual are in the [nixos/doc/manual](https://github.com/NixOS/nixpkgs/tree/master/nixos/doc/manual) subdirectory of the [Nixpkgs](https://github.com/NixOS/nixpkgs) repository.
+This manual uses the [Nixpkgs manual syntax](https://nixos.org/manual/nixpkgs/unstable/#sec-contributing-markup).
 
 You can quickly check your edits with the following:
 
 ```ShellSession
 $ cd /path/to/nixpkgs
+$ $EDITOR doc/nixos/manual/... # edit the manual
 $ nix-build nixos/release.nix -A manual.x86_64-linux
 ```
 
@@ -13,24 +15,96 @@ If the build succeeds, the manual will be in `./result/share/doc/nixos/index.htm
 
 There's also [a convenient development daemon](https://nixos.org/manual/nixpkgs/unstable/#sec-contributing-devmode).
 
-**Contributing to the man pages**
+The above instructions don't deal with the appendix of available `configuration.nix` options, and the manual pages related to NixOS. These are built, and written in a different location and in a different format, as explained in the next sections.
 
-The man pages are written in [DocBook] which is XML.
+## Contributing to the `configuration.nix` options documentation {#sec-contributing-options}
 
-To see what your edits look like:
+The documentation for all the different `configuration.nix` options is automatically generated by reading the `description`s of all the NixOS options defined at `nixos/modules/`. If you want to improve such `description`, find it in the `nixos/modules/` directory, and edit it and open a pull request.
+
+To see how your changes render on the web, run again:
+
+```ShellSession
+$ nix-build nixos/release.nix -A manual.x86_64-linux
+```
+
+And you'll see the changes to the appendix in the path `result/share/doc/nixos/options.html`.
+
+You can also build only the `configuration.nix(5)` manual page, via:
 
 ```ShellSession
 $ cd /path/to/nixpkgs
-$ nix-build nixos/release.nix -A manpages.x86_64-linux
+$ nix-build nixos/release.nix -A nixos-configuration-reference-manpage.x86_64-linux
 ```
 
-You can then read the man page you edited by running
+And observe the result via:
 
 ```ShellSession
-$ man --manpath=result/share/man nixos-rebuild # Replace nixos-rebuild with the command whose manual you edited
+$ man --local-file result/share/man/man5/configuration.nix.5
+```
+
+If you're on a different architecture that's supported by NixOS (check file `nixos/release.nix` on Nixpkgs' repository) then replace `x86_64-linux` with the architecture. `nix-build` will complain otherwise, but should also tell you which architecture you have + the supported ones.
+
+## Contributing to `nixos-*` tools' manpages {#sec-contributing-nixos-tools}
+
+The manual pages for the tools available in the installation image can be found in Nixpkgs by running (e.g for `nixos-rebuild`):
+
+```ShellSession
+$ git ls | grep nixos-rebuild.8
+```
+
+Man pages are written in [`mdoc(7)` format](https://mandoc.bsd.lv/man/mdoc.7.html) and should be portable between mandoc and groff for rendering (except for minor differences, notably different spacing rules.)
+
+For a preview, run `man --local-file path/to/file.8`.
+
+Being written in `mdoc`, these manpages use semantic markup. This following subsections provides a guideline on where to apply which semantic elements.
+
+### Command lines and arguments {#ssec-contributing-nixos-tools-cli-and-args}
+
+In any manpage, commands, flags and arguments to the *current* executable should be marked according to their semantics. Commands, flags and arguments passed to *other* executables should not be marked like this and should instead be considered as code examples and marked with `Ql`.
+
+- Use `Fl` to mark flag arguments, `Ar` for their arguments.
+- Repeating arguments should be marked by adding an ellipsis (spelled with periods, `...`).
+- Use `Cm` to mark literal string arguments, e.g. the `boot` command argument passed to `nixos-rebuild`.
+- Optional flags or arguments should be marked with `Op`. This includes optional repeating arguments.
+- Required flags or arguments should not be marked.
+- Mutually exclusive groups of arguments should be enclosed in curly brackets, preferably created with `Bro`/`Brc` blocks.
+
+When an argument is used in an example it should be marked up with `Ar` again to differentiate it from a constant. For example, a command with a `--host name` option that calls ssh to retrieve the host's local time would signify this thusly:
+```
+This will run
+.Ic ssh Ar name Ic time
+to retrieve the remote time.
 ```
 
-If you're on a different architecture that's supported by NixOS (check nixos/release.nix) then replace `x86_64-linux` with the architecture.
-`nix-build` will complain otherwise, but should also tell you which architecture you have + the supported ones.
+### Paths, NixOS options, environment variables {#ssec-contributing-nixos-tools-options-and-environment}
+
+Constant paths should be marked with `Pa`, NixOS options with `Va`, and environment variables with `Ev`.
+
+Generated paths, e.g. `result/bin/run-hostname-vm` (where `hostname` is a variable or arguments) should be marked as `Ql` inline literals with their variable components marked appropriately.
+
+ - When `hostname` refers to an argument, it becomes `.Ql result/bin/run- Ns Ar hostname Ns -vm`
+ - When `hostname` refers to a variable, it becomes `.Ql result/bin/run- Ns Va hostname Ns -vm`
+
+### Code examples and other commands {#ssec-contributing-nixos-tools-code-examples}
 
-[DocBook]: https://en.wikipedia.org/wiki/DocBook
+In free text names and complete invocations of other commands (e.g. `ssh` or `tar -xvf src.tar`) should be marked with `Ic`, fragments of command lines should be marked with `Ql`.
+
+Larger code blocks or those that cannot be shown inline should use indented literal display block markup for their contents, i.e.
+
+```
+.Bd -literal -offset indent
+...
+.Ed
+```
+
+Contents of code blocks may be marked up further, e.g. if they refer to arguments that will be substituted into them:
+
+```
+.Bd -literal -offset indent
+{
+  config.networking.hostname = "\c
+.Ar hostname Ns \c
+";
+}
+.Ed
+```
diff --git a/nixpkgs/nixos/doc/manual/default.nix b/nixpkgs/nixos/doc/manual/default.nix
index 902dee701801..a368b16201f8 100644
--- a/nixpkgs/nixos/doc/manual/default.nix
+++ b/nixpkgs/nixos/doc/manual/default.nix
@@ -184,8 +184,8 @@ in rec {
     '';
 
 
-  # Generate the NixOS manpages.
-  manpages = runCommand "nixos-manpages"
+  # Generate the `man configuration.nix` package
+  nixos-configuration-reference-manpage = runCommand "nixos-configuration-reference-manpage"
     { nativeBuildInputs = [
         buildPackages.installShellFiles
         buildPackages.nixos-render-docs
@@ -194,8 +194,6 @@ in rec {
     }
     ''
       # Generate manpages.
-      mkdir -p $out/share/man/man8
-      installManPage ${./manpages}/*
       mkdir -p $out/share/man/man5
       nixos-render-docs -j $NIX_BUILD_CORES options manpage \
         --revision ${lib.escapeShellArg revision} \
diff --git a/nixpkgs/nixos/doc/manual/manpages/README.md b/nixpkgs/nixos/doc/manual/manpages/README.md
deleted file mode 100644
index 05cb83902c74..000000000000
--- a/nixpkgs/nixos/doc/manual/manpages/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# NixOS manpages
-
-This is the collection of NixOS manpages, excluding `configuration.nix(5)`.
-
-Man pages are written in [`mdoc(7)` format](https://mandoc.bsd.lv/man/mdoc.7.html) and should be portable between mandoc and groff for rendering (though minor differences may occur, mandoc and groff seem to have slightly different spacing rules.)
-
-For previewing edited files, you can just run `man -l path/to/file.8` and you will see it rendered.
-
-Being written in `mdoc` these manpages use semantic markup. This file provides a guideline on where to apply which of the semantic elements of `mdoc`.
-
-### Command lines and arguments
-
-In any manpage, commands, flags and arguments to the *current* executable should be marked according to their semantics. Commands, flags and arguments passed to *other* executables should not be marked like this and should instead be considered as code examples and marked with `Ql`.
-
- - Use `Fl` to mark flag arguments, `Ar` for their arguments.
- - Repeating arguments should be marked by adding ellipses (`...`).
- - Use `Cm` to mark literal string arguments, e.g. the `boot` command argument passed to `nixos-rebuild`.
- - Optional flags or arguments should be marked with `Op`. This includes optional repeating arguments.
- - Required flags or arguments should not be marked.
- - Mutually exclusive groups of arguments should be enclosed in curly brackets, preferably created with `Bro`/`Brc` blocks.
-
-When an argument is used in an example it should be marked up with `Ar` again to differentiate it from a constant. For example, a command with a `--host name` flag that calls ssh to retrieve the host's local time would signify this thusly:
-```
-This will run
-.Ic ssh Ar name Ic time
-to retrieve the remote time.
-```
-
-### Paths, NixOS options, environment variables
-
-Constant paths should be marked with `Pa`, NixOS options with `Va`, and environment variables with `Ev`.
-
-Generated paths, e.g. `result/bin/run-hostname-vm` (where `hostname` is a variable or arguments) should be marked as `Ql` inline literals with their variable components marked appropriately.
-
- - Taking `hostname` from an argument become `.Ql result/bin/run- Ns Ar hostname Ns -vm`
- - Taking `hostname` from a variable otherwise defined becomes `.Ql result/bin/run- Ns Va hostname Ns -vm`
-
-### Code examples and other commands
-
-In free text names and complete invocations of other commands (e.g. `ssh` or `tar -xvf src.tar`) should be marked with `Ic`, fragments of command lines should be marked with `Ql`.
-
-Larger code blocks or those that cannot be shown inline should use indented literal display block markup for their contents, i.e.
-```
-.Bd -literal -offset indent
-...
-.Ed
-```
-Contents of code blocks may be marked up further, e.g. if they refer to arguments that will be substituted into them:
-```
-.Bd -literal -offset indent
-{
-  options.hostname = "\c
-.Ar hostname Ns \c
-";
-}
-.Ed
-```
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-option.8 b/nixpkgs/nixos/doc/manual/manpages/nixos-option.8
deleted file mode 100644
index 28438b03580b..000000000000
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-option.8
+++ /dev/null
@@ -1,89 +0,0 @@
-.Dd January 1, 1980
-.Dt nixos-option 8
-.Os
-.Sh NAME
-.Nm nixos-option
-.Nd inspect a NixOS configuration
-.
-.
-.
-.Sh SYNOPSIS
-.Nm
-.Op Fl r | -recursive
-.Op Fl I Ar path
-.Ar option.name
-.
-.
-.
-.Sh DESCRIPTION
-This command evaluates the configuration specified in
-.Pa /etc/nixos/configuration.nix
-and returns the properties of the option name given as argument.
-.
-.Pp
-When the option name is not an option, the command prints the list of attributes
-contained in the attribute set.
-.
-.
-.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl r , -recursive
-Print all the values at or below the specified path recursively.
-.
-.It Fl I Ar path
-This option is passed to the underlying
-.Xr nix-instantiate 1
-invocation.
-.El
-.
-.
-.
-.Sh ENVIRONMENT
-.Bl -tag -width indent
-.It Ev NIXOS_CONFIG
-Path to the main NixOS configuration module. Defaults to
-.Pa /etc/nixos/configuration.nix Ns
-\&.
-.El
-.
-.
-.
-.Sh EXAMPLES
-Investigate option values:
-.Bd -literal -offset indent
-$ nixos-option boot.loader
-This attribute set contains:
-generationsDir
-grub
-initScript
-
-$ nixos-option boot.loader.grub.enable
-Value:
-true
-
-Default:
-true
-
-Description:
-Whether to enable the GNU GRUB boot loader.
-
-Declared by:
-  "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
-
-Defined by:
-  "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
-.Ed
-.
-.
-.
-.Sh SEE ALSO
-.Xr configuration.nix 5
-.
-.
-.
-.Sh AUTHORS
-.An -nosplit
-.An Nicolas Pierron
-and
-.An the Nixpkgs/NixOS contributors
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-rebuild.8 b/nixpkgs/nixos/doc/manual/manpages/nixos-rebuild.8
deleted file mode 100644
index 64bbbee411d7..000000000000
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-rebuild.8
+++ /dev/null
@@ -1,452 +0,0 @@
-.Dd January 1, 1980
-.Dt nixos-rebuild 8
-.Os
-.Sh NAME
-.Nm nixos-rebuild
-.Nd reconfigure a NixOS machine
-.
-.
-.
-.Sh SYNOPSIS
-.Nm
-.Bro
-.Cm switch | boot | test | build | dry-build | dry-activate | edit | build-vm | build-vm-with-bootloader
-.Brc
-.br
-.Op Fl -upgrade | -upgrade-all
-.Op Fl -install-bootloader
-.Op Fl -no-build-nix
-.Op Fl -fast
-.Op Fl -rollback
-.Op Fl -builders Ar builder-spec
-.br
-.Op Fl -flake Ar flake-uri
-.Op Fl -no-flake
-.Op Fl -override-input Ar input-name flake-uri
-.br
-.Op Fl -profile-name | p Ar name
-.Op Fl -specialisation | c Ar name
-.br
-.Op Fl -build-host Va host
-.Op Fl -target-host Va host
-.Op Fl -use-remote-sudo
-.br
-.Op Fl -show-trace
-.Op Fl I Va NIX_PATH
-.Op Fl -verbose | v
-.Op Fl -impure
-.Op Fl -max-jobs | j Va number
-.Op Fl -keep-failed | K
-.Op Fl -keep-going | k
-.
-.
-.
-.Sh DESCRIPTION
-This command updates the system so that it corresponds to the
-configuration specified in
-.Pa /etc/nixos/configuration.nix
-or
-.Pa /etc/nixos/flake.nix Ns
-\&. Thus, every time you modify the configuration or any other NixOS module, you
-must run
-.Nm
-to make the changes take effect. It builds the new system in
-.Pa /nix/store Ns
-, runs its activation script, and stop and (re)starts any system services if
-needed. Please note that user services need to be started manually as they
-aren't detected by the activation script at the moment.
-.
-.Pp
-This command has one required argument, which specifies the desired
-operation. It must be one of the following:
-.Bl -tag -width indent
-.It Cm switch
-Build and activate the new configuration, and make it the boot default. That
-is, the configuration is added to the GRUB boot menu as the default
-menu entry, so that subsequent reboots will boot the system into the new
-configuration. Previous configurations activated with
-.Ic nixos-rebuild switch
-or
-.Ic nixos-rebuild boot
-remain available in the GRUB menu.
-.Pp
-Note that if you are using specializations, running just
-.Ic nixos-rebuild switch
-will switch you back to the unspecialized, base system \(em in that case, you
-might want to use this instead:
-.Bd -literal -offset indent
-$ nixos-rebuild switch --specialisation your-specialisation-name
-.Ed
-.Pp
-This command will build all specialisations and make them bootable just
-like regular
-.Ic nixos-rebuild switch
-does \(em the only thing different is that it will switch to given
-specialisation instead of the base system; it can be also used to switch from
-the base system into a specialised one, or to switch between specialisations.
-.
-.It Cm boot
-Build the new configuration and make it the boot default (as with
-.Ic nixos-rebuild switch Ns
-), but do not activate it. That is, the system continues to run the previous
-configuration until the next reboot.
-.
-.It Cm test
-Build and activate the new configuration, but do not add it to the GRUB
-boot menu. Thus, if you reboot the system (or if it crashes), you will
-automatically revert to the default configuration (i.e. the
-configuration resulting from the last call to
-.Ic nixos-rebuild switch
-or
-.Ic nixos-rebuild boot Ns
-).
-.Pp
-Note that if you are using specialisations, running just
-.Ic nixos-rebuild test
-will activate the unspecialised, base system \(em in that case, you might want
-to use this instead:
-.Bd -literal -offset indent
-$ nixos-rebuild test --specialisation your-specialisation-name
-.Ed
-.Pp
-This command can be also used to switch from the base system into a
-specialised one, or to switch between specialisations.
-.
-.It Cm build
-Build the new configuration, but neither activate it nor add it to the
-GRUB boot menu. It leaves a symlink named
-.Pa result
-in the current directory, which points to the output of the top-level
-.Dq system
-derivation. This is essentially the same as doing
-.Bd -literal -offset indent
-$ nix-build /path/to/nixpkgs/nixos -A system
-.Ed
-.Pp
-Note that you do not need to be root to run
-.Ic nixos-rebuild build Ns
-\&.
-.
-.It Cm dry-build
-Show what store paths would be built or downloaded by any of the
-operations above, but otherwise do nothing.
-.
-.It Cm dry-activate
-Build the new configuration, but instead of activating it, show what
-changes would be performed by the activation (i.e. by
-.Ic nixos-rebuild test Ns
-). For instance, this command will print which systemd units would be restarted.
-The list of changes is not guaranteed to be complete.
-.
-.It Cm edit
-Opens
-.Pa configuration.nix
-in the default editor.
-.
-.It Cm build-vm
-Build a script that starts a NixOS virtual machine with the desired
-configuration. It leaves a symlink
-.Pa result
-in the current directory that points (under
-.Ql result/bin/run\- Ns Va hostname Ns \-vm Ns
-)
-at the script that starts the VM. Thus, to test a NixOS configuration in
-a virtual machine, you should do the following:
-.Bd -literal -offset indent
-$ nixos-rebuild build-vm
-$ ./result/bin/run-*-vm
-.Ed
-.Pp
-The VM is implemented using the
-.Ql qemu
-package. For best performance, you should load the
-.Ql kvm-intel
-or
-.Ql kvm-amd
-kernel modules to get hardware virtualisation.
-.Pp
-The VM mounts the Nix store of the host through the 9P file system. The
-host Nix store is read-only, so Nix commands that modify the Nix store
-will not work in the VM. This includes commands such as
-.Nm Ns
-; to change the VM’s configuration, you must halt the VM and re-run the commands
-above.
-.Pp
-The VM has its own ext3 root file system, which is automatically created when
-the VM is first started, and is persistent across reboots of the VM. It is
-stored in
-.Ql ./ Ns Va hostname Ns .qcow2 Ns
-\&.
-.\" The entire file system hierarchy of the host is available in
-.\" the VM under
-.\" .Pa /hostfs Ns
-.\" .
-.
-.It Cm build-vm-with-bootloader
-Like
-.Cm build-vm Ns
-, but boots using the regular boot loader of your configuration (e.g. GRUB 1 or
-2), rather than booting directly into the kernel and initial ramdisk of the
-system. This allows you to test whether the boot loader works correctly. \
-However, it does not guarantee that your NixOS configuration will boot
-successfully on the host hardware (i.e., after running
-.Ic nixos-rebuild switch Ns
-), because the hardware and boot loader configuration in the VM are different.
-The boot loader is installed on an automatically generated virtual disk
-containing a
-.Pa /boot
-partition.
-.El
-.
-.
-.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl -upgrade , -upgrade-all
-Update the root user's channel named
-.Ql nixos
-before rebuilding the system.
-.Pp
-In addition to the
-.Ql nixos
-channel, the root user's channels which have a file named
-.Ql .update-on-nixos-rebuild
-in their base directory will also be updated.
-.Pp
-Passing
-.Fl -upgrade-all
-updates all of the root user's channels.
-.
-.It Fl -install-bootloader
-Causes the boot loader to be (re)installed on the device specified by the
-relevant configuration options.
-.
-.It Fl -no-build-nix
-Normally,
-.Nm
-first builds the
-.Ql nixUnstable
-attribute in Nixpkgs, and uses the resulting instance of the Nix package manager
-to build the new system configuration. This is necessary if the NixOS modules
-use features not provided by the currently installed version of Nix. This option
-disables building a new Nix.
-.
-.It Fl -fast
-Equivalent to
-.Fl -no-build-nix Ns
-\&. This option is useful if you call
-.Nm
-frequently (e.g. if you’re hacking on a NixOS module).
-.
-.It Fl -rollback
-Instead of building a new configuration as specified by
-.Pa /etc/nixos/configuration.nix Ns
-, roll back to the previous configuration. (The previous configuration is
-defined as the one before the “current” generation of the Nix profile
-.Pa /nix/var/nix/profiles/system Ns
-\&.)
-.
-.It Fl -builders Ar builder-spec
-Allow ad-hoc remote builders for building the new system. This requires
-the user executing
-.Nm
-(usually root) to be configured as a trusted user in the Nix daemon. This can be
-achieved by using the
-.Va nix.settings.trusted-users
-NixOS option. Examples values for that option are described in the
-.Dq Remote builds
-chapter in the Nix manual, (i.e.
-.Ql --builders \(dqssh://bigbrother x86_64-linux\(dq Ns
-). By specifying an empty string existing builders specified in
-.Pa /etc/nix/machines
-can be ignored:
-.Ql --builders \(dq\(dq
-for example when they are not reachable due to network connectivity.
-.
-.It Fl -profile-name Ar name , Fl p Ar name
-Instead of using the Nix profile
-.Pa /nix/var/nix/profiles/system
-to keep track of the current and previous system configurations, use
-.Pa /nix/var/nix/profiles/system-profiles/ Ns Va name Ns
-\&. When you use GRUB 2, for every system profile created with this flag, NixOS
-will create a submenu named
-.Dq NixOS - Profile Va name
-in GRUB’s boot menu, containing the current and previous configurations of this profile.
-.Pp
-For instance, if you want to test a configuration file named
-.Pa test.nix
-without affecting the default system profile, you would do:
-.Bd -literal -offset indent
-$ nixos-rebuild switch -p test -I nixos-config=./test.nix
-.Ed
-.Pp
-The new configuration will appear in the GRUB 2 submenu
-.Dq NixOS - Profile 'test' Ns
-\&.
-.
-.It Fl -specialisation Ar name , Fl c Ar name
-Activates given specialisation; when not specified, switching and testing
-will activate the base, unspecialised system.
-.
-.It Fl -build-host Ar host
-Instead of building the new configuration locally, use the specified host
-to perform the build. The host needs to be accessible with
-.Ic ssh Ns ,
-and must be able to perform Nix builds. If the option
-.Fl -target-host
-is not set, the build will be copied back to the local machine when done.
-.Pp
-Note that, if
-.Fl -no-build-nix
-is not specified, Nix will be built both locally and remotely. This is because
-the configuration will always be evaluated locally even though the building
-might be performed remotely.
-.Pp
-You can include a remote user name in the host name
-.Ns ( Va user@host Ns
-). You can also set ssh options by defining the
-.Ev NIX_SSHOPTS
-environment variable.
-.
-.It Fl -target-host Ar host
-Specifies the NixOS target host. By setting this to something other than an
-empty string, the system activation will happen on the remote host instead of
-the local machine. The remote host needs to be accessible over
-.Ic ssh Ns ,
-and for the commands
-.Cm switch Ns
-,
-.Cm boot
-and
-.Cm test
-you need root access.
-.Pp
-If
-.Fl -build-host
-is not explicitly specified or empty, building will take place locally.
-.Pp
-You can include a remote user name in the host name
-.Ns ( Va user@host Ns
-). You can also set ssh options by defining the
-.Ev NIX_SSHOPTS
-environment variable.
-.Pp
-Note that
-.Nm
-honors the
-.Va nixpkgs.crossSystem
-setting of the given configuration but disregards the true architecture of the
-target host. Hence the
-.Va nixpkgs.crossSystem
-setting has to match the target platform or else activation will fail.
-.
-.It Fl -use-substitutes
-When set, nixos-rebuild will add
-.Fl -use-substitutes
-to each invocation of nix-copy-closure. This will only affect the behavior of
-nixos-rebuild if
-.Fl -target-host
-or
-.Fl -build-host
-is also set. This is useful when the target-host connection to cache.nixos.org
-is faster than the connection between hosts.
-.
-.It Fl -use-remote-sudo
-When set, nixos-rebuild prefixes remote commands that run on the
-.Fl -build-host
-and
-.Fl -target-host
-systems with
-.Ic sudo Ns
-\&. Setting this option allows deploying as a non-root user.
-.
-.It Fl -flake Va flake-uri Ns Op Va #name
-Build the NixOS system from the specified flake. It defaults to the directory
-containing the target of the symlink
-.Pa /etc/nixos/flake.nix Ns
-, if it exists. The flake must contain an output named
-.Ql nixosConfigurations. Ns Va name Ns
-\&. If
-.Va name
-is omitted, it default to the current host name.
-.
-.It Fl -no-flake
-Do not imply
-.Fl -flake
-if
-.Pa /etc/nixos/flake.nix
-exists. With this option, it is possible to build non-flake NixOS configurations
-even if the current NixOS systems uses flakes.
-.El
-.Pp
-In addition,
-.Nm
-accepts various Nix-related flags, including
-.Fl -max-jobs Ns ,
-.Fl j Ns ,
-.Fl I Ns ,
-.Fl -show-trace Ns ,
-.Fl -keep-failed Ns ,
-.Fl -keep-going Ns ,
-.Fl -impure Ns ,
-.Fl -verbose Ns , and
-.Fl v Ns
-\&. See the Nix manual for details.
-.
-.
-.
-.Sh ENVIRONMENT
-.Bl -tag -width indent
-.It Ev NIXOS_CONFIG
-Path to the main NixOS configuration module. Defaults to
-.Pa /etc/nixos/configuration.nix Ns
-\&.
-.
-.It Ev NIX_PATH
-A colon-separated list of directories used to look up Nix expressions enclosed
-in angle brackets (e.g. <nixpkgs>). Example:
-.Bd -literal -offset indent
-nixpkgs=./my-nixpkgs
-.Ed
-.
-.It Ev NIX_SSHOPTS
-Additional options to be passed to
-.Ic ssh
-on the command line.
-.El
-.
-.
-.
-.Sh FILES
-.Bl -tag -width indent
-.It Pa /etc/nixos/flake.nix
-If this file exists, then
-.Nm
-will use it as if the
-.Fl -flake
-option was given. This file may be a symlink to a
-.Pa flake.nix
-in an actual flake; thus
-.Pa /etc/nixos
-need not be a flake.
-.
-.It Pa /run/current-system
-A symlink to the currently active system configuration in the Nix store.
-.
-.It Pa /nix/var/nix/profiles/system
-The Nix profile that contains the current and previous system
-configurations. Used to generate the GRUB boot menu.
-.El
-.
-.
-.
-.Sh BUGS
-This command should be renamed to something more descriptive.
-.
-.
-.
-.Sh AUTHORS
-.An -nosplit
-.An Eelco Dolstra
-and
-.An the Nixpkgs/NixOS contributors
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 c69e8b4317ce..825b1c5bd407 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -30,6 +30,8 @@
 
 - [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).
 
+- [Jool](https://nicmx.github.io/Jool/en/index.html), an Open Source implementation of IPv4/IPv6 translation on Linux. Available as [networking.jool.enable](#opt-networking.jool.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).
@@ -42,6 +44,8 @@
 
 - [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).
+
 ## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
 
 - 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.
@@ -66,6 +70,13 @@
 
 - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`.
 
+- 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.
+
 - `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
 
 - `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.
@@ -134,10 +145,26 @@
 
 - `pharo` has been updated to latest stable (PharoVM 10.0.5), 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 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`.
+
+- Emacs macport version 29 was introduced.
+
+- 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).
+
 ## Other Notable Changes {#sec-release-23.11-notable-changes}
 
 - 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 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:
+
+  ```nix
+  qt = {
+    enable = true;
+    platformTheme = "gnome";
+    style = "adwaita";
+  };
+  ```
+
 - `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 latest available version of Nextcloud is v27 (available as `pkgs.nextcloud27`). The installation logic is as follows:
@@ -158,6 +185,8 @@
 
 - `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.
 
+- 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).
+
 - 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.
@@ -182,6 +211,18 @@ The module update takes care of the new config syntax and the data itself (user
 
 - 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 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.
+
+  ```nix
+  python = python3.override {
+    packageOverrides = self: super: {
+      django = super.django_3;
+    };
+  };
+  ```
+
 - The `qemu-vm.nix` module by default now identifies block devices via
   persistent names available in `/dev/disk/by-*`. Because the rootDevice is
   identfied by its filesystem label, it needs to be formatted before the VM is
diff --git a/nixpkgs/nixos/lib/make-squashfs.nix b/nixpkgs/nixos/lib/make-squashfs.nix
index d1260a48f229..b7c7078b73b1 100644
--- a/nixpkgs/nixos/lib/make-squashfs.nix
+++ b/nixpkgs/nixos/lib/make-squashfs.nix
@@ -1,4 +1,4 @@
-{ stdenv, squashfsTools, closureInfo
+{ lib, stdenv, squashfsTools, closureInfo
 
 , # The root directory of the squashfs filesystem is filled with the
   # closures of the Nix store paths listed here.
@@ -22,11 +22,13 @@ stdenv.mkDerivation {
       # for nix-store --load-db.
       cp $closureInfo/registration nix-path-registration
 
+    '' + lib.optionalString stdenv.buildPlatform.is32bit ''
       # 64 cores on i686 does not work
       # fails with FATAL ERROR: mangle2:: xz compress failed with error code 5
       if ((NIX_BUILD_CORES > 48)); then
         NIX_BUILD_CORES=48
       fi
+    '' + ''
 
       # Generate the squashfs image.
       mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out \
diff --git a/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py b/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py
index db7e0ed33a89..c90e3d9e1cdb 100755
--- a/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py
+++ b/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py
@@ -106,7 +106,13 @@ def main() -> None:
         args.keep_vm_state,
     ) as driver:
         if args.interactive:
-            ptpython.repl.embed(driver.test_symbols(), {})
+            history_dir = os.getcwd()
+            history_path = os.path.join(history_dir, ".nixos-test-history")
+            ptpython.repl.embed(
+                driver.test_symbols(),
+                {},
+                history_filename=history_path,
+            )
         else:
             tic = time.time()
             driver.run_tests()
diff --git a/nixpkgs/nixos/modules/config/malloc.nix b/nixpkgs/nixos/modules/config/malloc.nix
index 3d70e091983b..043f78c8214e 100644
--- a/nixpkgs/nixos/modules/config/malloc.nix
+++ b/nixpkgs/nixos/modules/config/malloc.nix
@@ -97,7 +97,6 @@ in
   };
 
   config = mkIf (cfg.provider != "libc") {
-    boot.kernel.sysctl."vm.max_map_count" = mkIf (cfg.provider == "graphene-hardened") (mkDefault 1048576); # TODO: Default vm.max_map_count has been increased system-wide
     environment.etc."ld-nix.so.preload".text = ''
       ${providerLibPath}
     '';
diff --git a/nixpkgs/nixos/modules/config/no-x-libs.nix b/nixpkgs/nixos/modules/config/no-x-libs.nix
index f8622be59a1b..b2eb46f273b1 100644
--- a/nixpkgs/nixos/modules/config/no-x-libs.nix
+++ b/nixpkgs/nixos/modules/config/no-x-libs.nix
@@ -26,12 +26,7 @@ with lib;
 
     fonts.fontconfig.enable = false;
 
-    nixpkgs.overlays = singleton (self: super: let
-      packageOverrides = const (python-prev: {
-        # tk feature requires wayland which fails to compile
-        matplotlib = python-prev.matplotlib.override { enableGtk3 = false; enableTk = false; enableQt = false; };
-      });
-    in {
+    nixpkgs.overlays = singleton (const (super: {
       beam = super.beam_nox;
       cairo = super.cairo.override { x11Support = false; };
       dbus = super.dbus.override { x11Support = false; };
@@ -67,8 +62,12 @@ with lib;
       pango = super.pango.override { x11Support = false; };
       pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; };
       pipewire = super.pipewire.override { x11Support = false; };
-      python3 = super.python3.override { inherit packageOverrides; };
-      python3Packages = self.python3.pkgs; # required otherwise overlays from above are not forwarded
+      pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
+        (python-final: python-prev: {
+          # tk feature requires wayland which fails to compile
+          matplotlib = python-prev.matplotlib.override { enableTk = false; };
+        })
+      ];
       qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; };
       qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; });
       qt5 = super.qt5.overrideScope (const (super': {
@@ -79,6 +78,6 @@ with lib;
       util-linux = super.util-linux.override { translateManpages = false; };
       vim-full = super.vim-full.override { guiSupport = false; };
       zbar = super.zbar.override { enableVideo = false; withXorg = false; };
-    });
+    }));
   };
 }
diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
index e72194653f30..67c3afcf320a 100644
--- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix
+++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
@@ -1,21 +1,14 @@
-# This module provides the proprietary NVIDIA X11 / OpenGL drivers.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  nvidia_x11 = let
-    drivers = config.services.xserver.videoDrivers;
-    isDeprecated = str: (hasPrefix "nvidia" str) && (str != "nvidia");
-    hasDeprecated = drivers: any isDeprecated drivers;
-  in if (hasDeprecated drivers) then
-    throw ''
-      Selecting an nvidia driver has been modified for NixOS 19.03. The version is now set using `hardware.nvidia.package`.
-    ''
-  else if (elem "nvidia" drivers) then cfg.package else null;
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}: let
+  nvidia_x11 =
+    if (lib.elem "nvidia" config.services.xserver.videoDrivers)
+    then cfg.package
+    else null;
 
-  enabled = nvidia_x11 != null;
   cfg = config.hardware.nvidia;
 
   pCfg = cfg.prime;
@@ -23,90 +16,68 @@ let
   offloadCfg = pCfg.offload;
   reverseSyncCfg = pCfg.reverseSync;
   primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable;
-  nvidiaPersistencedEnabled =  cfg.nvidiaPersistenced;
-  nvidiaSettings = cfg.nvidiaSettings;
-  busIDType = types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?";
-
+  busIDType = lib.types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?";
   ibtSupport = cfg.open || (nvidia_x11.ibtSupport or false);
-in
-
-{
-  imports =
-    [
-      (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "enable" ] [ "hardware" "nvidia" "prime" "sync" "enable" ])
-      (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ])
-      (mkRenamedOptionModule [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ])
-      (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ])
-      (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ])
-    ];
-
+in {
   options = {
-    hardware.nvidia.powerManagement.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Experimental power management through systemd. For more information, see
+    hardware.nvidia = {
+      powerManagement.enable = lib.mkEnableOption (lib.mdDoc ''
+        experimental power management through systemd. For more information, see
         the NVIDIA docs, on Chapter 21. Configuring Power Management Support.
-      '';
-    };
+      '');
 
-    hardware.nvidia.powerManagement.finegrained = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Experimental power management of PRIME offload. For more information, see
-        the NVIDIA docs, chapter 22. PCI-Express runtime power management.
-      '';
-    };
+      powerManagement.finegrained = lib.mkEnableOption (lib.mdDoc ''
+        experimental power management of PRIME offload. For more information, see
+        the NVIDIA docs, on Chapter 22. PCI-Express Runtime D3 (RTD3) Power Management.
+      '');
+
+      dynamicBoost.enable = lib.mkEnableOption (lib.mdDoc ''
+        dynamic Boost balances power between the CPU and the GPU for improved
+        performance on supported laptops using the nvidia-powerd daemon. For more
+        information, see the NVIDIA docs, on Chapter 23. Dynamic Boost on Linux.
+      '');
 
-    hardware.nvidia.modesetting.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Enable kernel modesetting when using the NVIDIA proprietary driver.
+      modesetting.enable = lib.mkEnableOption (lib.mdDoc ''
+        kernel modesetting when using the NVIDIA proprietary driver.
 
         Enabling this fixes screen tearing when using Optimus via PRIME (see
         {option}`hardware.nvidia.prime.sync.enable`. This is not enabled
         by default because it is not officially supported by NVIDIA and would not
         work with SLI.
-      '';
-    };
+      '');
 
-    hardware.nvidia.prime.nvidiaBusId = mkOption {
-      type = busIDType;
-      default = "";
-      example = "PCI:1:0:0";
-      description = lib.mdDoc ''
-        Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
-        shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
-      '';
-    };
+      prime.nvidiaBusId = lib.mkOption {
+        type = busIDType;
+        default = "";
+        example = "PCI:1:0:0";
+        description = lib.mdDoc ''
+          Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
+          shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
+        '';
+      };
 
-    hardware.nvidia.prime.intelBusId = mkOption {
-      type = busIDType;
-      default = "";
-      example = "PCI:0:2:0";
-      description = lib.mdDoc ''
-        Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
-        shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
-      '';
-    };
+      prime.intelBusId = lib.mkOption {
+        type = busIDType;
+        default = "";
+        example = "PCI:0:2:0";
+        description = lib.mdDoc ''
+          Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
+          shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
+        '';
+      };
 
-    hardware.nvidia.prime.amdgpuBusId = mkOption {
-      type = busIDType;
-      default = "";
-      example = "PCI:4:0:0";
-      description = lib.mdDoc ''
-        Bus ID of the AMD APU. You can find it using lspci; for example if lspci
-        shows the AMD APU at "04:00.0", set this option to "PCI:4:0:0".
-      '';
-    };
+      prime.amdgpuBusId = lib.mkOption {
+        type = busIDType;
+        default = "";
+        example = "PCI:4:0:0";
+        description = lib.mdDoc ''
+          Bus ID of the AMD APU. You can find it using lspci; for example if lspci
+          shows the AMD APU at "04:00.0", set this option to "PCI:4:0:0".
+        '';
+      };
 
-    hardware.nvidia.prime.sync.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
+      prime.sync.enable = lib.mkEnableOption (lib.mdDoc ''
+        NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
         If enabled, the NVIDIA GPU will be always on and used for all rendering,
         while enabling output to displays attached only to the integrated Intel/AMD
         GPU without a multiplexer.
@@ -127,55 +98,39 @@ in
         Note that this configuration will only be successful when a display manager
         for which the {option}`services.xserver.displayManager.setupCommands`
         option is supported is used.
-      '';
-    };
+      '');
 
-    hardware.nvidia.prime.allowExternalGpu = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Configure X to allow external NVIDIA GPUs when using Prime [Reverse] sync optimus.
-      '';
-    };
+      prime.allowExternalGpu = lib.mkEnableOption (lib.mdDoc ''
+        configuring X to allow external NVIDIA GPUs when using Prime [Reverse] sync optimus.
+      '');
 
-    hardware.nvidia.prime.offload.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Enable render offload support using the NVIDIA proprietary driver via PRIME.
+      prime.offload.enable = lib.mkEnableOption (lib.mdDoc ''
+        render offload support using the NVIDIA proprietary driver via PRIME.
 
         If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
         be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and
         {option}`hardware.nvidia.prime.intelBusId` or
         {option}`hardware.nvidia.prime.amdgpuBusId`).
-      '';
-    };
+      '');
 
-    hardware.nvidia.prime.offload.enableOffloadCmd = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Adds a `nvidia-offload` convenience script to {option}`environment.systemPackages`
+      prime.offload.enableOffloadCmd = lib.mkEnableOption (lib.mdDoc ''
+        adding a `nvidia-offload` convenience script to {option}`environment.systemPackages`
         for offloading programs to an nvidia device. To work, should have also enabled
         {option}`hardware.nvidia.prime.offload.enable` or {option}`hardware.nvidia.prime.reverseSync.enable`.
 
         Example usage `nvidia-offload sauerbraten_client`.
-      '';
-    };
-
-    hardware.nvidia.prime.reverseSync.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Warning: This feature is relatively new, depending on your system this might
-        work poorly. AMD support, especially so.
-        See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828
+      '');
 
-        Enable NVIDIA Optimus support using the NVIDIA proprietary driver via reverse
+      prime.reverseSync.enable = lib.mkEnableOption (lib.mdDoc ''
+        NVIDIA Optimus support using the NVIDIA proprietary driver via reverse
         PRIME. If enabled, the Intel/AMD GPU will be used for all rendering, while
         enabling output to displays attached only to the NVIDIA GPU without a
         multiplexer.
 
+        Warning: This feature is relatively new, depending on your system this might
+        work poorly. AMD support, especially so.
+        See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828
+
         Note that this option only has any effect if the "nvidia" driver is specified
         in {option}`services.xserver.videoDrivers`, and it should preferably
         be the only driver there.
@@ -192,316 +147,347 @@ in
         Note that this configuration will only be successful when a display manager
         for which the {option}`services.xserver.displayManager.setupCommands`
         option is supported is used.
-      '';
-    };
+      '');
 
-    hardware.nvidia.nvidiaSettings = mkOption {
-      default = true;
-      type = types.bool;
-      description = lib.mdDoc ''
-        Whether to add nvidia-settings, NVIDIA's GUI configuration tool, to
-        systemPackages.
-      '';
-    };
+      nvidiaSettings =
+        (lib.mkEnableOption (lib.mdDoc ''
+          nvidia-settings, NVIDIA's GUI configuration tool.
+        ''))
+        // {default = true;};
 
-    hardware.nvidia.nvidiaPersistenced = mkOption {
-      default = false;
-      type = types.bool;
-      description = lib.mdDoc ''
-        Update for NVIDA GPU headless mode, i.e. nvidia-persistenced. It ensures all
-        GPUs stay awake even during headless mode.
-      '';
-    };
+      nvidiaPersistenced = lib.mkEnableOption (lib.mdDoc ''
+        nvidia-persistenced a update for NVIDIA GPU headless mode, i.e.
+        It ensures all GPUs stay awake even during headless mode.
+      '');
 
-    hardware.nvidia.forceFullCompositionPipeline = lib.mkOption {
-      default = false;
-      type = types.bool;
-      description = lib.mdDoc ''
-        Whether to force-enable the full composition pipeline.
+      forceFullCompositionPipeline = lib.mkEnableOption (lib.mdDoc ''
+        forcefully the full composition pipeline.
         This sometimes fixes screen tearing issues.
         This has been reported to reduce the performance of some OpenGL applications and may produce issues in WebGL.
         It also drastically increases the time the driver needs to clock down after load.
-      '';
-    };
+      '');
 
-    hardware.nvidia.package = lib.mkOption {
-      type = types.package;
-      default = config.boot.kernelPackages.nvidiaPackages.stable;
-      defaultText = literalExpression "config.boot.kernelPackages.nvidiaPackages.stable";
-      description = lib.mdDoc ''
-        The NVIDIA X11 derivation to use.
-      '';
-      example = literalExpression "config.boot.kernelPackages.nvidiaPackages.legacy_340";
-    };
+      package = lib.mkPackageOptionMD config.boot.kernelPackages.nvidiaPackages "nvidia_x11" {
+        default = "stable";
+        example = lib.mdDoc "config.boot.kernelPackages.nvidiaPackages.legacy_470";
+      };
 
-    hardware.nvidia.open = lib.mkOption {
-      type = lib.types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Whether to use the open source kernel module
-      '';
+      open = lib.mkEnableOption (lib.mdDoc ''
+        the open source NVIDIA kernel module
+      '');
     };
   };
 
   config = let
-      igpuDriver = if pCfg.intelBusId != "" then "modesetting" else "amdgpu";
-      igpuBusId = if pCfg.intelBusId != "" then pCfg.intelBusId else pCfg.amdgpuBusId;
-  in mkIf enabled {
-    assertions = [
-      {
-        assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
-        message = ''
-          You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.
-        '';
-      }
+    igpuDriver =
+      if pCfg.intelBusId != ""
+      then "modesetting"
+      else "amdgpu";
+    igpuBusId =
+      if pCfg.intelBusId != ""
+      then pCfg.intelBusId
+      else pCfg.amdgpuBusId;
+  in
+    lib.mkIf (nvidia_x11 != null) {
+      assertions = [
+        {
+          assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
+          message = "You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.";
+        }
+
+        {
+          assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
+          message = "Offload command requires offloading or reverse prime sync to be enabled.";
+        }
+
+        {
+          assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
+          message = "When NVIDIA PRIME is enabled, the GPU bus IDs must be configured.";
+        }
+
+        {
+          assertion = offloadCfg.enable -> lib.versionAtLeast nvidia_x11.version "435.21";
+          message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
+        }
+
+        {
+          assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> lib.versionAtLeast nvidia_x11.version "470.0";
+          message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
+        }
+
+        {
+          assertion = !(syncCfg.enable && offloadCfg.enable);
+          message = "PRIME Sync and Offload cannot be both enabled";
+        }
+
+        {
+          assertion = !(syncCfg.enable && reverseSyncCfg.enable);
+          message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
+        }
+
+        {
+          assertion = !(syncCfg.enable && cfg.powerManagement.finegrained);
+          message = "Sync precludes powering down the NVIDIA GPU.";
+        }
+
+        {
+          assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
+          message = "Fine-grained power management requires offload to be enabled.";
+        }
+
+        {
+          assertion = cfg.powerManagement.enable -> lib.versionAtLeast nvidia_x11.version "430.09";
+          message = "Required files for driver based power management only exist on versions >= 430.09.";
+        }
+
+        {
+          assertion = cfg.open -> (cfg.package ? open && cfg.package ? firmware);
+          message = "This version of NVIDIA driver does not provide a corresponding opensource kernel driver";
+        }
+
+        {
+          assertion = cfg.dynamicBoost.enable -> lib.versionAtLeast nvidia_x11.version "510.39.01";
+          message = "NVIDIA's Dynamic Boost feature only exists on versions >= 510.39.01";
+        }
+      ];
 
-      {
-        assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
-        message = ''
-          Offload command requires offloading or reverse prime sync to be enabled.
-        '';
-      }
+      # If Optimus/PRIME is enabled, we:
+      # - Specify the configured NVIDIA GPU bus ID in the Device section for the
+      #   "nvidia" driver.
+      # - Add the AllowEmptyInitialConfiguration option to the Screen section for the
+      #   "nvidia" driver, in order to allow the X server to start without any outputs.
+      # - Add a separate Device section for the Intel GPU, using the "modesetting"
+      #   driver and with the configured BusID.
+      # - OR add a separate Device section for the AMD APU, using the "amdgpu"
+      #   driver and with the configures BusID.
+      # - Reference that Device section from the ServerLayout section as an inactive
+      #   device.
+      # - Configure the display manager to run specific `xrandr` commands which will
+      #   configure/enable displays connected to the Intel iGPU / AMD APU.
+
+      # reverse sync implies offloading
+      hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable;
+
+      services.xserver.drivers =
+        lib.optional primeEnabled {
+          name = igpuDriver;
+          display = offloadCfg.enable;
+          modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu;
+          deviceSection =
+            ''
+              BusID "${igpuBusId}"
+            ''
+            + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''
+              Option "AccelMethod" "none"
+            '';
+        }
+        ++ lib.singleton {
+          name = "nvidia";
+          modules = [nvidia_x11.bin];
+          display = !offloadCfg.enable;
+          deviceSection =
+            lib.optionalString primeEnabled
+            ''
+              BusID "${pCfg.nvidiaBusId}"
+            ''
+            + lib.optionalString pCfg.allowExternalGpu ''
+              Option "AllowExternalGpus"
+            '';
+          screenSection =
+            ''
+              Option "RandRRotation" "on"
+            ''
+            + lib.optionalString syncCfg.enable ''
+              Option "AllowEmptyInitialConfiguration"
+            ''
+            + lib.optionalString cfg.forceFullCompositionPipeline ''
+              Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
+              Option         "AllowIndirectGLXProtocol" "off"
+              Option         "TripleBuffer" "on"
+            '';
+        };
 
-      {
-        assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
-        message = ''
-          When NVIDIA PRIME is enabled, the GPU bus IDs must be configured.
-        '';
-      }
-
-      {
-        assertion = offloadCfg.enable -> versionAtLeast nvidia_x11.version "435.21";
-        message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
-      }
-
-      {
-        assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> versionAtLeast nvidia_x11.version "470.0";
-        message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
-      }
-
-      {
-        assertion = !(syncCfg.enable && offloadCfg.enable);
-        message = "PRIME Sync and Offload cannot be both enabled";
-      }
-
-      {
-        assertion = !(syncCfg.enable && reverseSyncCfg.enable);
-        message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
-      }
-
-      {
-        assertion = !(syncCfg.enable && cfg.powerManagement.finegrained);
-        message = "Sync precludes powering down the NVIDIA GPU.";
-      }
-
-      {
-        assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
-        message = "Fine-grained power management requires offload to be enabled.";
-      }
-
-      {
-        assertion = cfg.powerManagement.enable -> versionAtLeast nvidia_x11.version "430.09";
-        message = "Required files for driver based power management only exist on versions >= 430.09.";
-      }
-
-      {
-        assertion = cfg.open -> (cfg.package ? open && cfg.package ? firmware);
-        message = "This version of NVIDIA driver does not provide a corresponding opensource kernel driver";
-      }
-    ];
-
-    # If Optimus/PRIME is enabled, we:
-    # - Specify the configured NVIDIA GPU bus ID in the Device section for the
-    #   "nvidia" driver.
-    # - Add the AllowEmptyInitialConfiguration option to the Screen section for the
-    #   "nvidia" driver, in order to allow the X server to start without any outputs.
-    # - Add a separate Device section for the Intel GPU, using the "modesetting"
-    #   driver and with the configured BusID.
-    # - OR add a separate Device section for the AMD APU, using the "amdgpu"
-    #   driver and with the configures BusID.
-    # - Reference that Device section from the ServerLayout section as an inactive
-    #   device.
-    # - Configure the display manager to run specific `xrandr` commands which will
-    #   configure/enable displays connected to the Intel iGPU / AMD APU.
-
-    # reverse sync implies offloading
-    hardware.nvidia.prime.offload.enable = mkDefault reverseSyncCfg.enable;
-
-    services.xserver.drivers = optional primeEnabled {
-      name = igpuDriver;
-      display = offloadCfg.enable;
-      modules = optionals (igpuDriver == "amdgpu") [ pkgs.xorg.xf86videoamdgpu ];
-      deviceSection = ''
-        BusID "${igpuBusId}"
-        ${optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''Option "AccelMethod" "none"''}
-      '';
-    } ++ singleton {
-      name = "nvidia";
-      modules = [ nvidia_x11.bin ];
-      display = !offloadCfg.enable;
-      deviceSection = optionalString primeEnabled
-        ''
-          BusID "${pCfg.nvidiaBusId}"
-          ${optionalString pCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
-        '';
-      screenSection =
+      services.xserver.serverLayoutSection =
+        lib.optionalString syncCfg.enable ''
+          Inactive "Device-${igpuDriver}[0]"
         ''
-          Option "RandRRotation" "on"
-        '' + optionalString syncCfg.enable ''
-          Option "AllowEmptyInitialConfiguration"
-        '' + optionalString cfg.forceFullCompositionPipeline ''
-          Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
-          Option         "AllowIndirectGLXProtocol" "off"
-          Option         "TripleBuffer" "on"
+        + lib.optionalString reverseSyncCfg.enable ''
+          Inactive "Device-nvidia[0]"
         ''
-        ;
-    };
+        + lib.optionalString offloadCfg.enable ''
+          Option "AllowNVIDIAGPUScreens"
+        '';
 
-    services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
-      Inactive "Device-${igpuDriver}[0]"
-    '' + optionalString reverseSyncCfg.enable ''
-      Inactive "Device-nvidia[0]"
-    '' + optionalString offloadCfg.enable ''
-      Option "AllowNVIDIAGPUScreens"
-    '';
-
-    services.xserver.displayManager.setupCommands = let
-      gpuProviderName = if igpuDriver == "amdgpu" then
-        # find the name of the provider if amdgpu
-        "`${pkgs.xorg.xrandr}/bin/xrandr --listproviders | ${pkgs.gnugrep}/bin/grep -i AMD | ${pkgs.gnused}/bin/sed -n 's/^.*name://p'`"
-      else
-        igpuDriver;
-      providerCmdParams = if syncCfg.enable then "\"${gpuProviderName}\" NVIDIA-0" else "NVIDIA-G0 \"${gpuProviderName}\"";
-    in optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
-      # Added by nvidia configuration module for Optimus/PRIME.
-      ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource ${providerCmdParams}
-      ${pkgs.xorg.xrandr}/bin/xrandr --auto
-    '';
-
-    environment.etc."nvidia/nvidia-application-profiles-rc" = mkIf nvidia_x11.useProfiles {
-      source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
-    };
+      services.xserver.displayManager.setupCommands = let
+        gpuProviderName =
+          if igpuDriver == "amdgpu"
+          then
+            # find the name of the provider if amdgpu
+            "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`"
+          else igpuDriver;
+        providerCmdParams =
+          if syncCfg.enable
+          then "\"${gpuProviderName}\" NVIDIA-0"
+          else "NVIDIA-G0 \"${gpuProviderName}\"";
+      in
+        lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
+          # Added by nvidia configuration module for Optimus/PRIME.
+          ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams}
+          ${lib.getExe pkgs.xorg.xrandr} --auto
+        '';
+
+      environment.etc = {
+        "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";};
 
-    # 'nvidia_x11' installs it's files to /run/opengl-driver/...
-    environment.etc."egl/egl_external_platform.d".source =
-      "/run/opengl-driver/share/egl/egl_external_platform.d/";
-
-    hardware.opengl.extraPackages = [
-      nvidia_x11.out
-      pkgs.nvidia-vaapi-driver
-    ];
-    hardware.opengl.extraPackages32 = [
-      nvidia_x11.lib32
-      pkgs.pkgsi686Linux.nvidia-vaapi-driver
-    ];
-
-    environment.systemPackages = [ nvidia_x11.bin ]
-      ++ optionals cfg.nvidiaSettings [ nvidia_x11.settings ]
-      ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ]
-      ++ optionals offloadCfg.enableOffloadCmd [
+        # 'nvidia_x11' installs it's files to /run/opengl-driver/...
+        "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/";
+      };
+
+      hardware.opengl = {
+        extraPackages = [
+          nvidia_x11.out
+          pkgs.nvidia-vaapi-driver
+        ];
+        extraPackages32 = [
+          nvidia_x11.lib32
+          pkgs.pkgsi686Linux.nvidia-vaapi-driver
+        ];
+      };
+      environment.systemPackages =
+        [nvidia_x11.bin]
+        ++ lib.optional cfg.nvidiaSettings nvidia_x11.settings
+        ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced
+        ++ lib.optional offloadCfg.enableOffloadCmd
         (pkgs.writeShellScriptBin "nvidia-offload" ''
           export __NV_PRIME_RENDER_OFFLOAD=1
           export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
           export __GLX_VENDOR_LIBRARY_NAME=nvidia
           export __VK_LAYER_NV_optimus=NVIDIA_only
           exec "$@"
-        '')
-      ];
-
-    systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out;
-
-    systemd.services = let
-      baseNvidiaService = state: {
-        description = "NVIDIA system ${state} actions";
+        '');
 
-        path = with pkgs; [ kbd ];
-        serviceConfig = {
-          Type = "oneshot";
-          ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
-        };
-      };
+      systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out;
 
-      nvidiaService = sleepState: (baseNvidiaService sleepState) // {
-        before = [ "systemd-${sleepState}.service" ];
-        requiredBy = [ "systemd-${sleepState}.service" ];
-      };
-
-      services = (builtins.listToAttrs (map (t: nameValuePair "nvidia-${t}" (nvidiaService t)) ["hibernate" "suspend"]))
-        // {
-          nvidia-resume = (baseNvidiaService "resume") // {
-            after = [ "systemd-suspend.service" "systemd-hibernate.service" ];
-            requiredBy = [ "systemd-suspend.service" "systemd-hibernate.service" ];
-          };
-        };
-    in optionalAttrs cfg.powerManagement.enable services
-      // optionalAttrs nvidiaPersistencedEnabled {
-        "nvidia-persistenced" = mkIf nvidiaPersistencedEnabled {
-          description = "NVIDIA Persistence Daemon";
-          wantedBy = [ "multi-user.target" ];
+      systemd.services = let
+        nvidiaService = state: {
+          description = "NVIDIA system ${state} actions";
+          path = [pkgs.kbd];
           serviceConfig = {
-            Type = "forking";
-            Restart = "always";
-            PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
-            ExecStart = "${nvidia_x11.persistenced}/bin/nvidia-persistenced --verbose";
-            ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+            Type = "oneshot";
+            ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
           };
+          before = ["systemd-${state}.service"];
+          requiredBy = ["systemd-${state}.service"];
         };
-      };
-
-    systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
+      in
+        lib.mkMerge [
+          (lib.mkIf cfg.powerManagement.enable {
+            nvidia-suspend = nvidiaService "suspend";
+            nvidia-hibernate = nvidiaService "hibernate";
+            nvidia-resume =
+              (nvidiaService "resume")
+              // {
+                before = [];
+                after = ["systemd-suspend.service" "systemd-hibernate.service"];
+                requiredBy = ["systemd-suspend.service" "systemd-hibernate.service"];
+              };
+          })
+          (lib.mkIf cfg.nvidiaPersistenced {
+            "nvidia-persistenced" = {
+              description = "NVIDIA Persistence Daemon";
+              wantedBy = ["multi-user.target"];
+              serviceConfig = {
+                Type = "forking";
+                Restart = "always";
+                PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
+                ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose";
+                ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
+              };
+            };
+          })
+          (lib.mkIf cfg.dynamicBoost.enable {
+            "nvidia-powerd" = {
+              description = "nvidia-powerd service";
+              path = [
+                pkgs.util-linux # nvidia-powerd wants lscpu
+              ];
+              wantedBy = ["multi-user.target"];
+              serviceConfig = {
+                Type = "dbus";
+                BusName = "nvidia.powerd.server";
+                ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd";
+              };
+            };
+          })
+        ];
+
+      services.acpid.enable = true;
+
+      services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin;
+
+      hardware.firmware = lib.optional cfg.open nvidia_x11.firmware;
+
+      systemd.tmpfiles.rules =
+        lib.optional config.virtualisation.docker.enableNvidia
         "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
-      ++ optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
+        ++ lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
         "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
 
-    boot.extraModulePackages = if cfg.open then [ nvidia_x11.open ] else [ nvidia_x11.bin ];
-    hardware.firmware = lib.optional cfg.open nvidia_x11.firmware;
-
-    # nvidia-uvm is required by CUDA applications.
-    boot.kernelModules = [ "nvidia-uvm" ] ++
-      optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
-
-    # If requested enable modesetting via kernel parameter.
-    boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
-      ++ optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
-      ++ optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1"
-      ++ optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off";
-
-    services.udev.extraRules =
-      ''
-        # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
-        KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) 255'"
-        KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \  -f 4); do mknod -m 666 /dev/nvidia$${i} c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) $${i}; done'"
-        KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) 254'"
-        KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
-        KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 1'"
-      '' + optionalString cfg.powerManagement.finegrained (
-      optionalString (versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
-        # Remove NVIDIA USB xHCI Host Controller devices, if present
-        ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
-
-        # Remove NVIDIA USB Type-C UCSI devices, if present
-        ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
-
-        # Remove NVIDIA Audio devices, if present
-        ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
-      '' + ''
-        # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
-        ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
-        ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
-
-        # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
-        ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
-        ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
-      '');
-
-    boot.extraModprobeConfig = mkIf cfg.powerManagement.finegrained ''
-      options nvidia "NVreg_DynamicPowerManagement=0x02"
-    '';
-
-    boot.blacklistedKernelModules = [ "nouveau" "nvidiafb" ];
-
-    services.acpid.enable = true;
-
-  };
+      boot = {
+        blacklistedKernelModules = ["nouveau" "nvidiafb"];
+
+        extraModulePackages =
+          if cfg.open
+          then [nvidia_x11.open]
+          else [nvidia_x11.bin];
+
+        # nvidia-uvm is required by CUDA applications.
+        kernelModules =
+          ["nvidia-uvm"]
+          ++ lib.optionals config.services.xserver.enable ["nvidia" "nvidia_modeset" "nvidia_drm"];
+
+        # If requested enable modesetting via kernel parameter.
+        kernelParams =
+          lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
+          ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"
+          ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1"
+          ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off";
+
+        # enable finegrained power management
+        extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained ''
+          options nvidia "NVreg_DynamicPowerManagement=0x02"
+        '';
+      };
 
+      services.udev.extraRules =
+        ''
+          # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
+          KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) 255'"
+          KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \  -f 4); do mknod -m 666 /dev/nvidia$${i} c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) $${i}; done'"
+          KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \  -f 1) 254'"
+          KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
+          KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 1'"
+        ''
+        + lib.optionalString cfg.powerManagement.finegrained (
+          lib.optionalString (lib.versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
+            # Remove NVIDIA USB xHCI Host Controller devices, if present
+            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
+
+            # Remove NVIDIA USB Type-C UCSI devices, if present
+            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
+
+            # Remove NVIDIA Audio devices, if present
+            ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
+          ''
+          + ''
+            # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
+            ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
+            ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
+
+            # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
+            ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
+            ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
+          ''
+        );
+    };
 }
diff --git a/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix b/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix
index 39952d6c3999..3d52c08888ea 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/fcitx5.nix
@@ -6,6 +6,7 @@ let
   im = config.i18n.inputMethod;
   cfg = im.fcitx5;
   fcitx5Package = pkgs.fcitx5-with-addons.override { inherit (cfg) addons; };
+  settingsFormat = pkgs.formats.ini { };
 in
 {
   options = {
@@ -19,7 +20,7 @@ in
         '';
       };
       quickPhrase = mkOption {
-        type = with types; attrsOf string;
+        type = with types; attrsOf str;
         default = { };
         example = literalExpression ''
           {
@@ -40,6 +41,44 @@ in
         '';
         description = lib.mdDoc "Quick phrase files.";
       };
+      settings = {
+        globalOptions = lib.mkOption {
+          type = lib.types.submodule {
+            freeformType = settingsFormat.type;
+          };
+          default = { };
+          description = lib.mdDoc ''
+            The global options in `config` file in ini format.
+          '';
+        };
+        inputMethod = lib.mkOption {
+          type = lib.types.submodule {
+            freeformType = settingsFormat.type;
+          };
+          default = { };
+          description = lib.mdDoc ''
+            The input method configure in `profile` file in ini format.
+          '';
+        };
+        addons = lib.mkOption {
+          type = with lib.types; (attrsOf anything);
+          default = { };
+          description = lib.mdDoc ''
+            The addon configures in `conf` folder in ini format with global sections.
+            Each item is written to the corresponding file.
+          '';
+          example = literalExpression "{ pinyin.globalSection.EmojiEnabled = \"True\"; }";
+        };
+      };
+      ignoreUserConfig = lib.mkOption {
+        type = lib.types.bool;
+        default = false;
+        description = lib.mdDoc ''
+          Ignore the user configures. **Warning**: When this is enabled, the
+          user config files are totally ignored and the user dict can't be saved
+          and loaded.
+        '';
+      };
     };
   };
 
@@ -61,12 +100,30 @@ in
         (name: value: lib.nameValuePair ("share/fcitx5/data/quickphrase.d/${name}.mb") value)
         cfg.quickPhraseFiles))
     ];
+    environment.etc =
+      let
+        optionalFile = p: f: v: lib.optionalAttrs (v != { }) {
+          "xdg/fcitx5/${p}".text = f v;
+        };
+      in
+      lib.attrsets.mergeAttrsList [
+        (optionalFile "config" (lib.generators.toINI { }) cfg.settings.globalOptions)
+        (optionalFile "profile" (lib.generators.toINI { }) cfg.settings.inputMethod)
+        (lib.concatMapAttrs
+          (name: value: optionalFile
+            "conf/${name}.conf"
+            (lib.generators.toINIWithGlobalSection { })
+            value)
+          cfg.settings.addons)
+      ];
 
     environment.variables = {
       GTK_IM_MODULE = "fcitx";
       QT_IM_MODULE = "fcitx";
       XMODIFIERS = "@im=fcitx";
       QT_PLUGIN_PATH = [ "${fcitx5Package}/${pkgs.qt6.qtbase.qtPluginPrefix}" ];
+    } // lib.optionalAttrs cfg.ignoreUserConfig {
+      SKIP_FCITX_USER_PATH = "1";
     };
   };
 }
diff --git a/nixpkgs/nixos/modules/image/repart.nix b/nixpkgs/nixos/modules/image/repart.nix
index 4362982f5bac..4a0021e9a56e 100644
--- a/nixpkgs/nixos/modules/image/repart.nix
+++ b/nixpkgs/nixos/modules/image/repart.nix
@@ -88,6 +88,13 @@ in
       '';
     };
 
+    package = lib.mkPackageOption pkgs "systemd-repart" {
+      default = "systemd";
+      example = lib.literalExpression ''
+        pkgs.systemdMinimal.override { withCryptsetup = true; }
+      '';
+    };
+
     partitions = lib.mkOption {
       type = with lib.types; attrsOf (submodule partitionOptions);
       default = { };
@@ -178,9 +185,9 @@ in
       in
       pkgs.runCommand cfg.name
         {
-          nativeBuildInputs = with pkgs; [
-            fakeroot
-            systemd
+          nativeBuildInputs = [
+            cfg.package
+            pkgs.fakeroot
           ] ++ fileSystemTools;
         } ''
         amendedRepartDefinitions=$(${amendRepartDefinitions} ${partitions} ${definitionsDirectory})
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix
index 12feb2d96ecc..d1a4c27432c2 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix
@@ -30,12 +30,6 @@
     enable = true;
   };
 
-  # Theme calamares with GNOME theme
-  qt = {
-    enable = true;
-    platformTheme = "gnome";
-  };
-
   # Fix scaling for calamares on wayland
   environment.variables = {
     QT_QPA_PLATFORM = "$([[ $XDG_SESSION_TYPE = \"wayland\" ]] && echo \"wayland\")";
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-build-vms.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8
index 6a8f2c42eddf..6a8f2c42eddf 100644
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-build-vms.8
+++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-build-vms.8
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-enter.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8
index 646f92199d62..646f92199d62 100644
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-enter.8
+++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-enter.8
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-generate-config.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8
index 1b95599e156a..1b95599e156a 100644
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-generate-config.8
+++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-generate-config.8
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-install.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8
index c6c8ed15224d..c6c8ed15224d 100644
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-install.8
+++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-install.8
diff --git a/nixpkgs/nixos/doc/manual/manpages/nixos-version.8 b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8
index f661611599fb..f661611599fb 100644
--- a/nixpkgs/nixos/doc/manual/manpages/nixos-version.8
+++ b/nixpkgs/nixos/modules/installer/tools/manpages/nixos-version.8
diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
index 582334a5aeaf..10c37a46fdac 100644
--- a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,7 +1,7 @@
 {
-  x86_64-linux = "/nix/store/ny9r65799s7xhp605bc2753sjvzkxrrs-nix-2.15.1";
-  i686-linux = "/nix/store/ck55dz5klc7szi8rx9ghhm8gi2b5q5bw-nix-2.15.1";
-  aarch64-linux = "/nix/store/cl0a02vr28913dgw98hrm45a4baqr3z1-nix-2.15.1";
-  x86_64-darwin = "/nix/store/wq228jdbz16pp2lnxf32n8dv27pw53p8-nix-2.15.1";
-  aarch64-darwin = "/nix/store/x11cpsjg4q236msfz5scc325pfp9xy64-nix-2.15.1";
+  x86_64-linux = "/nix/store/3wqasl97rjiza3vd7fxjnvli2w9l30mk-nix-2.17.0";
+  i686-linux = "/nix/store/z360xswxfx55pmm1fng3hw748rbs0kkj-nix-2.17.0";
+  aarch64-linux = "/nix/store/9670sxa916xmv8n1kqs7cdvmnsrhrdjv-nix-2.17.0";
+  x86_64-darwin = "/nix/store/2rdbky9j8hc3mbgl6pnda4hkjllyfwnn-nix-2.17.0";
+  aarch64-darwin = "/nix/store/jl9qma14fb4zk9lq1k0syw2k9qm2gqjw-nix-2.17.0";
 }
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 4dce4f998052..6564b583464a 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -9,12 +9,19 @@ let
   makeProg = args: pkgs.substituteAll (args // {
     dir = "bin";
     isExecutable = true;
+    nativeBuildInputs = [
+      pkgs.installShellFiles
+    ];
+    postInstall = ''
+      installManPage ${args.manPage}
+    '';
   });
 
   nixos-build-vms = makeProg {
     name = "nixos-build-vms";
     src = ./nixos-build-vms/nixos-build-vms.sh;
     inherit (pkgs) runtimeShell;
+    manPage = ./manpages/nixos-build-vms.8;
   };
 
   nixos-install = makeProg {
@@ -27,6 +34,7 @@ let
       nixos-enter
       pkgs.util-linuxMinimal
     ];
+    manPage = ./manpages/nixos-install.8;
   };
 
   nixos-rebuild = pkgs.nixos-rebuild.override { nix = config.nix.package.out; };
@@ -40,6 +48,7 @@ let
     btrfs = "${pkgs.btrfs-progs}/bin/btrfs";
     inherit (config.system.nixos-generate-config) configuration desktopConfiguration;
     xserverEnabled = config.services.xserver.enable;
+    manPage = ./manpages/nixos-generate-config.8;
   };
 
   inherit (pkgs) nixos-option;
@@ -57,6 +66,7 @@ let
     } // optionalAttrs (config.system.configurationRevision != null) {
       configurationRevision = config.system.configurationRevision;
     });
+    manPage = ./manpages/nixos-version.8;
   };
 
   nixos-enter = makeProg {
@@ -66,6 +76,7 @@ let
     path = makeBinPath [
       pkgs.util-linuxMinimal
     ];
+    manPage = ./manpages/nixos-enter.8;
   };
 
 in
diff --git a/nixpkgs/nixos/modules/misc/documentation.nix b/nixpkgs/nixos/modules/misc/documentation.nix
index d9222fd0a622..1111a4cf3c7a 100644
--- a/nixpkgs/nixos/modules/misc/documentation.nix
+++ b/nixpkgs/nixos/modules/misc/documentation.nix
@@ -354,7 +354,7 @@ in
       system.build.manual = manual;
 
       environment.systemPackages = []
-        ++ optional cfg.man.enable manual.manpages
+        ++ optional cfg.man.enable manual.nixos-configuration-reference-manpage
         ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ];
     })
 
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index bcd6a235eb63..f05e28cd14bc 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -319,6 +319,7 @@
   ./services/audio/botamusique.nix
   ./services/audio/gmediarender.nix
   ./services/audio/gonic.nix
+  ./services/audio/goxlr-utility.nix
   ./services/audio/hqplayerd.nix
   ./services/audio/icecast.nix
   ./services/audio/jack.nix
@@ -808,6 +809,7 @@
   ./services/network-filesystems/davfs2.nix
   ./services/network-filesystems/diod.nix
   ./services/network-filesystems/drbd.nix
+  ./services/network-filesystems/eris-server.nix
   ./services/network-filesystems/glusterfs.nix
   ./services/network-filesystems/kbfs.nix
   ./services/network-filesystems/kubo.nix
@@ -865,6 +867,7 @@
   ./services/networking/coturn.nix
   ./services/networking/create_ap.nix
   ./services/networking/croc.nix
+  ./services/networking/dae.nix
   ./services/networking/dante.nix
   ./services/networking/dhcpcd.nix
   ./services/networking/dnscache.nix
@@ -927,6 +930,7 @@
   ./services/networking/jibri/default.nix
   ./services/networking/jicofo.nix
   ./services/networking/jitsi-videobridge.nix
+  ./services/networking/jool.nix
   ./services/networking/kea.nix
   ./services/networking/keepalived/default.nix
   ./services/networking/keybase.nix
@@ -1463,6 +1467,7 @@
   ./virtualisation/lxc.nix
   ./virtualisation/lxcfs.nix
   ./virtualisation/lxd.nix
+  ./virtualisation/lxd-agent.nix
   ./virtualisation/multipass.nix
   ./virtualisation/nixos-containers.nix
   ./virtualisation/oci-containers.nix
diff --git a/nixpkgs/nixos/modules/profiles/installation-device.nix b/nixpkgs/nixos/modules/profiles/installation-device.nix
index 4120d5919d7d..19e7eb32e833 100644
--- a/nixpkgs/nixos/modules/profiles/installation-device.nix
+++ b/nixpkgs/nixos/modules/profiles/installation-device.nix
@@ -120,5 +120,8 @@ with lib;
       [PStore]
       Unlink=no
     '';
+
+    # allow nix-copy to live system
+    nix.settings.trusted-users = [ "root" "nixos" ];
   };
 }
diff --git a/nixpkgs/nixos/modules/programs/captive-browser.nix b/nixpkgs/nixos/modules/programs/captive-browser.nix
index 36ceb1a69610..032c0e71f1f4 100644
--- a/nixpkgs/nixos/modules/programs/captive-browser.nix
+++ b/nixpkgs/nixos/modules/programs/captive-browser.nix
@@ -7,6 +7,8 @@ let
     concatStringsSep escapeShellArgs optionalString
     literalExpression mkEnableOption mkIf mkOption mkOptionDefault types;
 
+  requiresSetcapWrapper = config.boot.kernelPackages.kernelOlder "5.7" && cfg.bindInterface;
+
   browserDefault = chromium: concatStringsSep " " [
     ''env XDG_CONFIG_HOME="$PREV_CONFIG_HOME"''
     ''${chromium}/bin/chromium''
@@ -23,11 +25,23 @@ let
   desktopItem = pkgs.makeDesktopItem {
     name = "captive-browser";
     desktopName = "Captive Portal Browser";
-    exec = "/run/wrappers/bin/captive-browser";
+    exec = "captive-browser";
     icon = "nix-snowflake";
     categories = [ "Network" ];
   };
 
+  captive-browser-configured = pkgs.writeShellScriptBin "captive-browser" ''
+    export PREV_CONFIG_HOME="$XDG_CONFIG_HOME"
+    export XDG_CONFIG_HOME=${pkgs.writeTextDir "captive-browser.toml" ''
+      browser = """${cfg.browser}"""
+      dhcp-dns = """${cfg.dhcp-dns}"""
+      socks5-addr = """${cfg.socks5-addr}"""
+      ${optionalString cfg.bindInterface ''
+        bind-device = """${cfg.interface}"""
+      ''}
+    ''}
+    exec ${cfg.package}/bin/captive-browser
+  '';
 in
 {
   ###### interface
@@ -101,6 +115,7 @@ in
       (pkgs.runCommand "captive-browser-desktop-item" { } ''
         install -Dm444 -t $out/share/applications ${desktopItem}/share/applications/*.desktop
       '')
+      captive-browser-configured
     ];
 
     programs.captive-browser.dhcp-dns =
@@ -131,22 +146,11 @@ in
       source = "${pkgs.busybox}/bin/udhcpc";
     };
 
-    security.wrappers.captive-browser = {
+    security.wrappers.captive-browser = mkIf requiresSetcapWrapper {
       owner = "root";
       group = "root";
       capabilities = "cap_net_raw+p";
-      source = pkgs.writeShellScript "captive-browser" ''
-        export PREV_CONFIG_HOME="$XDG_CONFIG_HOME"
-        export XDG_CONFIG_HOME=${pkgs.writeTextDir "captive-browser.toml" ''
-                                  browser = """${cfg.browser}"""
-                                  dhcp-dns = """${cfg.dhcp-dns}"""
-                                  socks5-addr = """${cfg.socks5-addr}"""
-                                  ${optionalString cfg.bindInterface ''
-                                    bind-device = """${cfg.interface}"""
-                                  ''}
-                                ''}
-        exec ${cfg.package}/bin/captive-browser
-      '';
+      source = "${captive-browser-configured}/bin/captive-browser";
     };
   };
 }
diff --git a/nixpkgs/nixos/modules/programs/environment.nix b/nixpkgs/nixos/modules/programs/environment.nix
index a448727be778..3fbda153e0b4 100644
--- a/nixpkgs/nixos/modules/programs/environment.nix
+++ b/nixpkgs/nixos/modules/programs/environment.nix
@@ -51,13 +51,6 @@ in
 
     environment.extraInit =
       ''
-         unset ASPELL_CONF
-         for i in ${concatStringsSep " " (reverseList cfg.profiles)} ; do
-           if [ -d "$i/lib/aspell" ]; then
-             export ASPELL_CONF="dict-dir $i/lib/aspell"
-           fi
-         done
-
          export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
          export NIX_PROFILES="${concatStringsSep " " (reverseList cfg.profiles)}"
       '';
diff --git a/nixpkgs/nixos/modules/programs/firefox.nix b/nixpkgs/nixos/modules/programs/firefox.nix
index d67bbee9a761..8653f066cf8f 100644
--- a/nixpkgs/nixos/modules/programs/firefox.nix
+++ b/nixpkgs/nixos/modules/programs/firefox.nix
@@ -53,7 +53,7 @@ in
     };
 
     preferences = mkOption {
-      type = with types; attrsOf (oneOf [ bool int string ]);
+      type = with types; attrsOf (oneOf [ bool int str ]);
       default = { };
       description = mdDoc ''
         Preferences to set from `about:config`.
diff --git a/nixpkgs/nixos/modules/programs/fish.nix b/nixpkgs/nixos/modules/programs/fish.nix
index 8b78d3d9e2b2..c85097f45e92 100644
--- a/nixpkgs/nixos/modules/programs/fish.nix
+++ b/nixpkgs/nixos/modules/programs/fish.nix
@@ -271,7 +271,7 @@ in
             ''
               mkdir -p $out
               if [ -d $package/share/man ]; then
-                find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
+                find $package/share/man -type f | xargs ${pkgs.python3.pythonForBuild.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
               fi
             '';
         in
diff --git a/nixpkgs/nixos/modules/programs/gamescope.nix b/nixpkgs/nixos/modules/programs/gamescope.nix
index c4424849a41e..a31295e736df 100644
--- a/nixpkgs/nixos/modules/programs/gamescope.nix
+++ b/nixpkgs/nixos/modules/programs/gamescope.nix
@@ -42,7 +42,7 @@ in
     };
 
     args = mkOption {
-      type = types.listOf types.string;
+      type = types.listOf types.str;
       default = [ ];
       example = [ "--rt" "--prefer-vk-device 8086:9bc4" ];
       description = mdDoc ''
@@ -51,7 +51,7 @@ in
     };
 
     env = mkOption {
-      type = types.attrsOf types.string;
+      type = types.attrsOf types.str;
       default = { };
       example = literalExpression ''
         # for Prime render offload on Nvidia laptops.
diff --git a/nixpkgs/nixos/modules/programs/htop.nix b/nixpkgs/nixos/modules/programs/htop.nix
index 2682ced490ca..777ea709836e 100644
--- a/nixpkgs/nixos/modules/programs/htop.nix
+++ b/nixpkgs/nixos/modules/programs/htop.nix
@@ -9,7 +9,8 @@ let
   fmt = value:
     if isList value then concatStringsSep " " (map fmt value) else
     if isString value then value else
-    if isBool value || isInt value then toString value else
+    if isBool value then if value then "1" else "0" else
+    if isInt value then toString value else
     throw "Unrecognized type ${typeOf value} in htop settings";
 
 in
diff --git a/nixpkgs/nixos/modules/programs/hyprland.nix b/nixpkgs/nixos/modules/programs/hyprland.nix
index faeaa8973fa9..e0ee5b6bd2a4 100644
--- a/nixpkgs/nixos/modules/programs/hyprland.nix
+++ b/nixpkgs/nixos/modules/programs/hyprland.nix
@@ -32,11 +32,10 @@ in
       readOnly = true;
       default = cfg.package.override {
         enableXWayland = cfg.xwayland.enable;
-        hidpiXWayland = cfg.xwayland.hidpi;
-        nvidiaPatches = cfg.nvidiaPatches;
+        enableNvidiaPatches = cfg.enableNvidiaPatches;
       };
       defaultText = literalExpression
-        "`wayland.windowManager.hyprland.package` with applied configuration";
+        "`programs.hyprland.package` with applied configuration";
       description = mdDoc ''
         The Hyprland package after applying configuration.
       '';
@@ -44,17 +43,9 @@ in
 
     portalPackage = mkPackageOptionMD pkgs "xdg-desktop-portal-hyprland" { };
 
-    xwayland = {
-      enable = mkEnableOption (mdDoc "XWayland") // { default = true; };
-      hidpi = mkEnableOption null // {
-        description = mdDoc ''
-          Enable HiDPI XWayland, based on [XWayland MR 733](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733).
-          See <https://wiki.hyprland.org/Nix/Options-Overrides/#xwayland-hidpi> for more info.
-        '';
-      };
-    };
+    xwayland.enable = mkEnableOption (mdDoc "XWayland") // { default = true; };
 
-    nvidiaPatches = mkEnableOption (mdDoc "patching wlroots for better Nvidia support");
+    enableNvidiaPatches = mkEnableOption (mdDoc "patching wlroots for better Nvidia support");
   };
 
   config = mkIf cfg.enable {
@@ -77,4 +68,15 @@ in
       extraPortals = [ finalPortalPackage ];
     };
   };
+
+  imports = with lib; [
+    (mkRemovedOptionModule
+      [ "programs" "hyprland" "xwayland" "hidpi" ]
+      "XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland"
+    )
+    (mkRenamedOptionModule
+      [ "programs" "hyprland" "nvidiaPatches" ]
+      [ "programs" "hyprland" "enableNvidiaPatches" ]
+    )
+  ];
 }
diff --git a/nixpkgs/nixos/modules/programs/steam.nix b/nixpkgs/nixos/modules/programs/steam.nix
index c63b31bde11f..29c449c16946 100644
--- a/nixpkgs/nixos/modules/programs/steam.nix
+++ b/nixpkgs/nixos/modules/programs/steam.nix
@@ -89,7 +89,7 @@ in {
         options = {
           enable = mkEnableOption (mdDoc "GameScope Session");
           args = mkOption {
-            type = types.listOf types.string;
+            type = types.listOf types.str;
             default = [ ];
             description = mdDoc ''
               Arguments to be passed to GameScope for the session.
@@ -97,7 +97,7 @@ in {
           };
 
           env = mkOption {
-            type = types.attrsOf types.string;
+            type = types.attrsOf types.str;
             default = { };
             description = mdDoc ''
               Environmental variables to be passed to GameScope for the session.
diff --git a/nixpkgs/nixos/modules/security/ipa.nix b/nixpkgs/nixos/modules/security/ipa.nix
index 7075be95040e..69a670cd5e4a 100644
--- a/nixpkgs/nixos/modules/security/ipa.nix
+++ b/nixpkgs/nixos/modules/security/ipa.nix
@@ -86,7 +86,7 @@ in {
       };
 
       ifpAllowedUids = mkOption {
-        type = types.listOf types.string;
+        type = types.listOf types.str;
         default = ["root"];
         description = lib.mdDoc "A list of users allowed to access the ifp dbus interface.";
       };
diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix
index ac9da4a823b7..a431817fe1bb 100644
--- a/nixpkgs/nixos/modules/security/pam.nix
+++ b/nixpkgs/nixos/modules/security/pam.nix
@@ -697,7 +697,7 @@ let
             session required ${config.systemd.package}/lib/security/pam_systemd_home.so
           '' +
           optionalString cfg.makeHomeDir ''
-            session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077
+            session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=${config.security.pam.makeHomeDir.umask}
           '' +
           optionalString cfg.updateWtmp ''
             session required ${pkgs.pam}/lib/security/pam_lastlog.so silent
@@ -902,6 +902,16 @@ in
       '';
     };
 
+    security.pam.makeHomeDir.umask = mkOption {
+      type = types.str;
+      default = "0077";
+      example = "0022";
+      description = lib.mdDoc ''
+        The user file mode creation mask to use on home directories
+        newly created by `pam_mkhomedir`.
+      '';
+    };
+
     security.pam.enableSSHAgentAuth = mkOption {
       type = types.bool;
       default = false;
@@ -934,7 +944,7 @@ in
       };
       authserver = mkOption {
         default = null;
-        type = with types; nullOr string;
+        type = with types; nullOr str;
         description = lib.mdDoc ''
           This controls the hostname for the 9front authentication server
           that users will be authenticated against.
diff --git a/nixpkgs/nixos/modules/security/wrappers/wrapper.c b/nixpkgs/nixos/modules/security/wrappers/wrapper.c
index a21ec500208d..17776a97af81 100644
--- a/nixpkgs/nixos/modules/security/wrappers/wrapper.c
+++ b/nixpkgs/nixos/modules/security/wrappers/wrapper.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,7 +17,10 @@
 #include <syscall.h>
 #include <byteswap.h>
 
+// aborts when false, printing the failed expression
 #define ASSERT(expr) ((expr) ? (void) 0 : assert_failure(#expr))
+// aborts when returns non-zero, printing the failed expression and errno
+#define MUSTSUCCEED(expr) ((expr) ? print_errno_and_die(#expr) : (void) 0)
 
 extern char **environ;
 
@@ -41,6 +45,12 @@ static noreturn void assert_failure(const char *assertion) {
     abort();
 }
 
+static noreturn void print_errno_and_die(const char *assertion) {
+    fprintf(stderr, "Call `%s` in NixOS's wrapper.c failed: %s\n", assertion, strerror(errno));
+    fflush(stderr);
+    abort();
+}
+
 int get_last_cap(unsigned *last_cap) {
     FILE* file = fopen("/proc/sys/kernel/cap_last_cap", "r");
     if (file == NULL) {
@@ -177,6 +187,17 @@ int main(int argc, char **argv) {
         fprintf(stderr, "cannot readlink /proc/self/exe: %s", strerror(-self_path_size));
     }
 
+    unsigned int ruid, euid, suid, rgid, egid, sgid;
+    MUSTSUCCEED(getresuid(&ruid, &euid, &suid));
+    MUSTSUCCEED(getresgid(&rgid, &egid, &sgid));
+
+    // If true, then we did not benefit from setuid privilege escalation,
+    // where the original uid is still in ruid and different from euid == suid.
+    int didnt_suid = (ruid == euid) && (euid == suid);
+    // If true, then we did not benefit from setgid privilege escalation
+    int didnt_sgid = (rgid == egid) && (egid == sgid);
+
+
     // Make sure that we are being executed from the right location,
     // i.e., `safe_wrapper_dir'.  This is to prevent someone from creating
     // hard link `X' from some other location, along with a false
@@ -189,15 +210,22 @@ int main(int argc, char **argv) {
     ASSERT('/' == wrapper_dir[0]);
     ASSERT('/' == self_path[len]);
 
-    // Make *really* *really* sure that we were executed as
-    // `self_path', and not, say, as some other setuid program. That
-    // is, our effective uid/gid should match the uid/gid of
-    // `self_path'.
+    // If we got privileges with the fs set[ug]id bit, check that the privilege we
+    // got matches the one one we expected, ie that our effective uid/gid
+    // matches the uid/gid of `self_path`. This ensures that we were executed as
+    // `self_path', and not, say, as some other setuid program.
+    // We don't check that if we did not benefit from the set[ug]id bit, as
+    // can be the case in nosuid mounts or user namespaces.
     struct stat st;
     ASSERT(lstat(self_path, &st) != -1);
 
-    ASSERT(!(st.st_mode & S_ISUID) || (st.st_uid == geteuid()));
-    ASSERT(!(st.st_mode & S_ISGID) || (st.st_gid == getegid()));
+    // if the wrapper gained privilege with suid, check that we got the uid of the file owner
+    ASSERT(!((st.st_mode & S_ISUID) && !didnt_suid) || (st.st_uid == euid));
+    // if the wrapper gained privilege with sgid, check that we got the gid of the file group
+    ASSERT(!((st.st_mode & S_ISGID) && !didnt_sgid) || (st.st_gid == egid));
+    // same, but with suid instead of euid
+    ASSERT(!((st.st_mode & S_ISUID) && !didnt_suid) || (st.st_uid == suid));
+    ASSERT(!((st.st_mode & S_ISGID) && !didnt_sgid) || (st.st_gid == sgid));
 
     // And, of course, we shouldn't be writable.
     ASSERT(!(st.st_mode & (S_IWGRP | S_IWOTH)));
diff --git a/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix b/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix
new file mode 100644
index 000000000000..b719de875c7f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/audio/goxlr-utility.nix
@@ -0,0 +1,48 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.goxlr-utility;
+in
+
+with lib;
+{
+
+  options = {
+    services.goxlr-utility = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = lib.mdDoc ''
+          Whether to enable goxlr-utility for controlling your TC-Helicon GoXLR or GoXLR Mini
+        '';
+      };
+      package = mkPackageOptionMD pkgs "goxlr-utility" { };
+      autoStart.xdg = mkOption {
+        default = true;
+        type = with types; bool;
+        description = lib.mdDoc ''
+          Start the daemon automatically using XDG autostart.
+          Sets `xdg.autostart.enable = true` if not already enabled.
+        '';
+      };
+    };
+  };
+
+  config = mkIf config.services.goxlr-utility.enable
+    {
+      services.udev.packages = [ cfg.package ];
+
+      xdg.autostart.enable = mkIf cfg.autoStart.xdg true;
+      environment.systemPackages = mkIf cfg.autoStart.xdg
+        [
+          cfg.package
+          (pkgs.makeAutostartItem
+            {
+              name = "goxlr-utility";
+              package = cfg.package;
+            })
+        ];
+    };
+
+  meta.maintainers = with maintainers; [ errnoh ];
+}
diff --git a/nixpkgs/nixos/modules/services/audio/liquidsoap.nix b/nixpkgs/nixos/modules/services/audio/liquidsoap.nix
index 5c10d13af5fd..9e61a7979619 100644
--- a/nixpkgs/nixos/modules/services/audio/liquidsoap.nix
+++ b/nixpkgs/nixos/modules/services/audio/liquidsoap.nix
@@ -18,6 +18,7 @@ let
           ExecStart = "${pkgs.liquidsoap}/bin/liquidsoap ${stream}";
           User = "liquidsoap";
           LogsDirectory = "liquidsoap";
+          Restart = "always";
         };
       };
     };
diff --git a/nixpkgs/nixos/modules/services/cluster/patroni/default.nix b/nixpkgs/nixos/modules/services/cluster/patroni/default.nix
index 9bf3a285836c..5ab016a9f59f 100644
--- a/nixpkgs/nixos/modules/services/cluster/patroni/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/patroni/default.nix
@@ -105,7 +105,7 @@ in
     };
 
     otherNodesIps = mkOption {
-      type = types.listOf types.string;
+      type = types.listOf types.str;
       example = [ "192.168.1.2" "192.168.1.3" ];
       description = mdDoc ''
         IP addresses of the other nodes.
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 fb70c4899126..d8d25898e294 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/gitea-actions-runner.nix
@@ -31,6 +31,8 @@ let
 
   cfg = config.services.gitea-actions-runner;
 
+  settingsFormat = pkgs.formats.yaml { };
+
   # Check whether any runner instance label requires a container runtime
   # Empty label strings result in the upstream defined defaultLabels, which require docker
   # https://gitea.com/gitea/act_runner/src/tag/v0.1.5/internal/app/cmd/register.go#L93-L98
@@ -119,6 +121,18 @@ in
               that follows the filesystem hierarchy standard.
             '';
           };
+          settings = mkOption {
+            description = lib.mdDoc ''
+              Configuration for `act_runner daemon`.
+              See https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml for an example configuration
+            '';
+
+            type = types.submodule {
+              freeformType = settingsFormat.type;
+            };
+
+            default = { };
+          };
 
           hostPackages = mkOption {
             type = listOf package;
@@ -169,6 +183,7 @@ in
         wantsHost = hasHostScheme instance;
         wantsDocker = wantsContainerRuntime && config.virtualisation.docker.enable;
         wantsPodman = wantsContainerRuntime && config.virtualisation.podman.enable;
+        configFile = settingsFormat.generate "config.yaml" instance.settings;
       in
         nameValuePair "gitea-runner-${escapeSystemdPath name}" {
           inherit (instance) enable;
@@ -196,7 +211,12 @@ in
             User = "gitea-runner";
             StateDirectory = "gitea-runner";
             WorkingDirectory = "-/var/lib/gitea-runner/${name}";
-            ExecStartPre = pkgs.writeShellScript "gitea-register-runner-${name}" ''
+
+            # gitea-runner might fail when gitea is restarted during upgrade.
+            Restart = "on-failure";
+            RestartSec = 2;
+
+            ExecStartPre = [(pkgs.writeShellScript "gitea-register-runner-${name}" ''
               export INSTANCE_DIR="$STATE_DIRECTORY/${name}"
               mkdir -vp "$INSTANCE_DIR"
               cd "$INSTANCE_DIR"
@@ -221,8 +241,8 @@ in
                 echo "$LABELS_WANTED" > "$LABELS_FILE"
               fi
 
-            '';
-            ExecStart = "${cfg.package}/bin/act_runner daemon";
+            '')];
+            ExecStart = "${cfg.package}/bin/act_runner daemon --config ${configFile}";
             SupplementaryGroups = optionals (wantsDocker) [
               "docker"
             ] ++ optionals (wantsPodman) [
diff --git a/nixpkgs/nixos/modules/services/databases/influxdb2.nix b/nixpkgs/nixos/modules/services/databases/influxdb2.nix
index e74de66ddc2f..329533b35dc8 100644
--- a/nixpkgs/nixos/modules/services/databases/influxdb2.nix
+++ b/nixpkgs/nixos/modules/services/databases/influxdb2.nix
@@ -1,8 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit
+    (lib)
+    escapeShellArg
+    hasAttr
+    literalExpression
+    mkEnableOption
+    mkIf
+    mkOption
+    types
+    ;
+
   format = pkgs.formats.json { };
   cfg = config.services.influxdb2;
   configFile = format.generate "config.json" cfg.settings;
@@ -24,14 +33,60 @@ in
         description = lib.mdDoc ''configuration options for influxdb2, see <https://docs.influxdata.com/influxdb/v2.0/reference/config-options> for details.'';
         type = format.type;
       };
+
+      provision = {
+        enable = mkEnableOption "initial database setup and provisioning";
+
+        initialSetup = {
+          organization = mkOption {
+            type = types.str;
+            example = "main";
+            description = "Primary organization name";
+          };
+
+          bucket = mkOption {
+            type = types.str;
+            example = "example";
+            description = "Primary bucket name";
+          };
+
+          username = mkOption {
+            type = types.str;
+            default = "admin";
+            description = "Primary username";
+          };
+
+          retention = mkOption {
+            type = types.str;
+            default = "0";
+            description = ''
+              The duration for which the bucket will retain data (0 is infinite).
+              Accepted units are `ns` (nanoseconds), `us` or `µs` (microseconds), `ms` (milliseconds),
+              `s` (seconds), `m` (minutes), `h` (hours), `d` (days) and `w` (weeks).
+            '';
+          };
+
+          passwordFile = mkOption {
+            type = types.path;
+            description = "Password for primary user. Don't use a file from the nix store!";
+          };
+
+          tokenFile = mkOption {
+            type = types.path;
+            description = "API Token to set for the admin user. Don't use a file from the nix store!";
+          };
+        };
+      };
     };
   };
 
   config = mkIf cfg.enable {
-    assertions = [{
-      assertion = !(builtins.hasAttr "bolt-path" cfg.settings) && !(builtins.hasAttr "engine-path" cfg.settings);
-      message = "services.influxdb2.config: bolt-path and engine-path should not be set as they are managed by systemd";
-    }];
+    assertions = [
+      {
+        assertion = !(hasAttr "bolt-path" cfg.settings) && !(hasAttr "engine-path" cfg.settings);
+        message = "services.influxdb2.config: bolt-path and engine-path should not be set as they are managed by systemd";
+      }
+    ];
 
     systemd.services.influxdb2 = {
       description = "InfluxDB is an open-source, distributed, time series database";
@@ -52,7 +107,62 @@ in
         LimitNOFILE = 65536;
         KillMode = "control-group";
         Restart = "on-failure";
+        LoadCredential = mkIf cfg.provision.enable [
+          "admin-password:${cfg.provision.initialSetup.passwordFile}"
+          "admin-token:${cfg.provision.initialSetup.tokenFile}"
+        ];
       };
+
+      path = [pkgs.influxdb2-cli];
+
+      # Mark if this is the first startup so postStart can do the initial setup
+      preStart = mkIf cfg.provision.enable ''
+        if ! test -e "$STATE_DIRECTORY/influxd.bolt"; then
+          touch "$STATE_DIRECTORY/.first_startup"
+        fi
+      '';
+
+      postStart = let
+        initCfg = cfg.provision.initialSetup;
+      in mkIf cfg.provision.enable (
+        ''
+          set -euo pipefail
+          export INFLUX_HOST="http://"${escapeShellArg (cfg.settings.http-bind-address or "localhost:8086")}
+
+          # Wait for the influxdb server to come online
+          count=0
+          while ! influx ping &>/dev/null; do
+            if [ "$count" -eq 300 ]; then
+              echo "Tried for 30 seconds, giving up..."
+              exit 1
+            fi
+
+            if ! kill -0 "$MAINPID"; then
+              echo "Main server died, giving up..."
+              exit 1
+            fi
+
+            sleep 0.1
+            count=$((count++))
+          done
+
+          # Do the initial database setup. Pass /dev/null as configs-path to
+          # avoid saving the token as the active config.
+          if test -e "$STATE_DIRECTORY/.first_startup"; then
+            influx setup \
+              --configs-path /dev/null \
+              --org ${escapeShellArg initCfg.organization} \
+              --bucket ${escapeShellArg initCfg.bucket} \
+              --username ${escapeShellArg initCfg.username} \
+              --password "$(< "$CREDENTIALS_DIRECTORY/admin-password")" \
+              --token "$(< "$CREDENTIALS_DIRECTORY/admin-token")" \
+              --retention ${escapeShellArg initCfg.retention} \
+              --force >/dev/null
+
+            rm -f "$STATE_DIRECTORY/.first_startup"
+          fi
+        ''
+      );
     };
 
     users.extraUsers.influxdb2 = {
@@ -63,5 +173,5 @@ in
     users.extraGroups.influxdb2 = {};
   };
 
-  meta.maintainers = with lib.maintainers; [ nickcao ];
+  meta.maintainers = with lib.maintainers; [ nickcao oddlama ];
 }
diff --git a/nixpkgs/nixos/modules/services/games/openarena.nix b/nixpkgs/nixos/modules/services/games/openarena.nix
index 89e30d7c12af..8f6d4986903f 100644
--- a/nixpkgs/nixos/modules/services/games/openarena.nix
+++ b/nixpkgs/nixos/modules/services/games/openarena.nix
@@ -1,14 +1,14 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib) concatStringsSep mkEnableOption mkIf mkOption types;
   cfg = config.services.openarena;
 in
 {
   options = {
     services.openarena = {
       enable = mkEnableOption (lib.mdDoc "OpenArena");
+      package = lib.mkPackageOptionMD pkgs "openarena" { };
 
       openPorts = mkOption {
         type = types.bool;
@@ -43,7 +43,7 @@ in
       serviceConfig = {
         DynamicUser = true;
         StateDirectory = "openarena";
-        ExecStart = "${pkgs.openarena}/bin/oa_ded +set fs_basepath ${pkgs.openarena}/openarena-0.8.8 +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
+        ExecStart = "${cfg.package}/bin/oa_ded +set fs_basepath ${cfg.package}/share/openarena +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
         Restart = "on-failure";
 
         # Hardening
diff --git a/nixpkgs/nixos/modules/services/games/quake3-server.nix b/nixpkgs/nixos/modules/services/games/quake3-server.nix
index 2d2148237da1..e51830c12e78 100644
--- a/nixpkgs/nixos/modules/services/games/quake3-server.nix
+++ b/nixpkgs/nixos/modules/services/games/quake3-server.nix
@@ -1,13 +1,15 @@
 { config, pkgs, lib, ... }:
-with lib;
 
 let
+  inherit (lib) literalMD mkEnableOption mkIf mkOption types;
   cfg = config.services.quake3-server;
+
   configFile = pkgs.writeText "q3ds-extra.cfg" ''
     set net_port ${builtins.toString cfg.port}
 
     ${cfg.extraConfig}
   '';
+
   defaultBaseq3 = pkgs.requireFile rec {
     name = "baseq3";
     hashMode = "recursive";
@@ -25,6 +27,7 @@ let
       $services.quake3-server.baseq3/.q3a/
     '';
   };
+
   home = pkgs.runCommand "quake3-home" {} ''
       mkdir -p $out/.q3a/baseq3
 
@@ -38,6 +41,7 @@ in {
   options = {
     services.quake3-server = {
       enable = mkEnableOption (lib.mdDoc "Quake 3 dedicated server");
+      package = lib.mkPackageOptionMD pkgs "ioquake3" { };
 
       port = mkOption {
         type = types.port;
@@ -103,10 +107,10 @@ in {
         ReadOnlyPaths = if baseq3InStore then home else cfg.baseq3;
         ExecStartPre = optionalString (!baseq3InStore) "+${pkgs.coreutils}/bin/cp ${configFile} ${cfg.baseq3}/.q3a/baseq3/nix.cfg";
 
-        ExecStart = "${pkgs.ioquake3}/ioq3ded.x86_64 +exec nix.cfg";
+        ExecStart = "${cfg.package}/bin/ioq3ded +exec nix.cfg";
       };
     };
   };
 
-  meta.maintainers = with maintainers; [ f4814n ];
+  meta.maintainers = with lib.maintainers; [ f4814n ];
 }
diff --git a/nixpkgs/nixos/modules/services/hardware/keyd.nix b/nixpkgs/nixos/modules/services/hardware/keyd.nix
index 969383fd4dc7..ead2f456a202 100644
--- a/nixpkgs/nixos/modules/services/hardware/keyd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/keyd.nix
@@ -7,7 +7,7 @@ let
   keyboardOptions = { ... }: {
     options = {
       ids = mkOption {
-        type = types.listOf types.string;
+        type = types.listOf types.str;
         default = [ "*" ];
         example = [ "*" "-0123:0456" ];
         description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/services/logging/graylog.nix b/nixpkgs/nixos/modules/services/logging/graylog.nix
index 1eb51c50ff79..673930c4cb5c 100644
--- a/nixpkgs/nixos/modules/services/logging/graylog.nix
+++ b/nixpkgs/nixos/modules/services/logging/graylog.nix
@@ -37,8 +37,8 @@ in
 
       package = mkOption {
         type = types.package;
-        default = if versionOlder config.system.stateVersion "23.05" then pkgs.graylog-3_3 else pkgs.graylog-5_0;
-        defaultText = literalExpression (if versionOlder config.system.stateVersion "23.05" then "pkgs.graylog-3_3" else "pkgs.graylog-5_0");
+        default = if versionOlder config.system.stateVersion "23.05" then pkgs.graylog-3_3 else pkgs.graylog-5_1;
+        defaultText = literalExpression (if versionOlder config.system.stateVersion "23.05" then "pkgs.graylog-3_3" else "pkgs.graylog-5_1");
         description = lib.mdDoc "Graylog package to use.";
       };
 
diff --git a/nixpkgs/nixos/modules/services/mail/maddy.nix b/nixpkgs/nixos/modules/services/mail/maddy.nix
index 3b4a517fb859..2c4d75e8391a 100644
--- a/nixpkgs/nixos/modules/services/mail/maddy.nix
+++ b/nixpkgs/nixos/modules/services/mail/maddy.nix
@@ -142,7 +142,7 @@ in {
 
       user = mkOption {
         default = "maddy";
-        type = with types; uniq string;
+        type = with types; uniq str;
         description = lib.mdDoc ''
           User account under which maddy runs.
 
@@ -156,7 +156,7 @@ in {
 
       group = mkOption {
         default = "maddy";
-        type = with types; uniq string;
+        type = with types; uniq str;
         description = lib.mdDoc ''
           Group account under which maddy runs.
 
@@ -170,7 +170,7 @@ in {
 
       hostname = mkOption {
         default = "localhost";
-        type = with types; uniq string;
+        type = with types; uniq str;
         example = ''example.com'';
         description = lib.mdDoc ''
           Hostname to use. It should be FQDN.
@@ -179,7 +179,7 @@ in {
 
       primaryDomain = mkOption {
         default = "localhost";
-        type = with types; uniq string;
+        type = with types; uniq str;
         example = ''mail.example.com'';
         description = lib.mdDoc ''
           Primary MX domain to use. It should be FQDN.
diff --git a/nixpkgs/nixos/modules/services/matrix/conduit.nix b/nixpkgs/nixos/modules/services/matrix/conduit.nix
index 16c4f571da94..76af7ba22857 100644
--- a/nixpkgs/nixos/modules/services/matrix/conduit.nix
+++ b/nixpkgs/nixos/modules/services/matrix/conduit.nix
@@ -94,6 +94,16 @@ in
                 instance will require manual migration of data.
               '';
             };
+            global.allow_check_for_updates = mkOption {
+              type = types.bool;
+              default = false;
+              description = lib.mdDoc ''
+                Whether to allow Conduit to automatically contact
+                <https://conduit.rs> hourly to check for important Conduit news.
+
+                Disabled by default because nixpkgs handles updates.
+              '';
+            };
           };
         };
         default = {};
diff --git a/nixpkgs/nixos/modules/services/matrix/synapse.md b/nixpkgs/nixos/modules/services/matrix/synapse.md
index cad91ebf58d5..1d22805b472f 100644
--- a/nixpkgs/nixos/modules/services/matrix/synapse.md
+++ b/nixpkgs/nixos/modules/services/matrix/synapse.md
@@ -27,7 +27,8 @@ please refer to the
 { pkgs, lib, config, ... }:
 let
   fqdn = "${config.networking.hostName}.${config.networking.domain}";
-  clientConfig."m.homeserver".base_url = "https://${fqdn}";
+  baseUrl = "https://${fqdn}";
+  clientConfig."m.homeserver".base_url = baseUrl;
   serverConfig."m.server" = "${fqdn}:443";
   mkWellKnown = data: ''
     add_header Content-Type application/json;
@@ -97,6 +98,11 @@ in {
   services.matrix-synapse = {
     enable = true;
     settings.server_name = config.networking.domain;
+    # The public base URL value must match the `base_url` value set in `clientConfig` above.
+    # The default value here is based on `server_name`, so if your `server_name` is different
+    # from the value of `fqdn` above, you will likely run into some mismatched domain names
+    # in client applications.
+    settings.public_baseurl = baseUrl;
     settings.listeners = [
       { port = 8008;
         bind_addresses = [ "::1" ];
diff --git a/nixpkgs/nixos/modules/services/matrix/synapse.nix b/nixpkgs/nixos/modules/services/matrix/synapse.nix
index 3dca3ff94f21..ef69a8adebb0 100644
--- a/nixpkgs/nixos/modules/services/matrix/synapse.nix
+++ b/nixpkgs/nixos/modules/services/matrix/synapse.nix
@@ -9,11 +9,6 @@ let
   # remove null values from the final configuration
   finalSettings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings;
   configFile = format.generate "homeserver.yaml" finalSettings;
-  logConfigFile = format.generate "log_config.yaml" cfg.logConfig;
-
-  pluginsEnv = cfg.package.python.buildEnv.override {
-    extraLibs = cfg.plugins;
-  };
 
   usePostgresql = cfg.settings.database.name == "psycopg2";
   hasLocalPostgresDB = let args = cfg.settings.database.args; in
@@ -50,6 +45,29 @@ let
             "${bindAddress}"
         }:${builtins.toString listener.port}/"
     '';
+
+  defaultExtras = [
+    "systemd"
+    "postgres"
+    "url-preview"
+    "user-search"
+  ];
+
+  wantedExtras = cfg.extras
+    ++ lib.optional (cfg.settings ? oidc_providers) "oidc"
+    ++ lib.optional (cfg.settings ? jwt_config) "jwt"
+    ++ lib.optional (cfg.settings ? saml2_config) "saml2"
+    ++ lib.optional (cfg.settings ? opentracing) "opentracing"
+    ++ lib.optional (cfg.settings ? redis) "redis"
+    ++ lib.optional (cfg.settings ? sentry) "sentry"
+    ++ lib.optional (cfg.settings ? user_directory) "user-search"
+    ++ lib.optional (cfg.settings.url_preview_enabled) "url-preview"
+    ++ lib.optional (cfg.settings.database.name == "psycopg2") "postgres";
+
+  wrapped = pkgs.matrix-synapse.override {
+    extras = wantedExtras;
+    inherit (cfg) plugins;
+  };
 in {
 
   imports = [
@@ -151,10 +169,53 @@ in {
 
       package = mkOption {
         type = types.package;
-        default = pkgs.matrix-synapse;
-        defaultText = literalExpression "pkgs.matrix-synapse";
+        readOnly = true;
+        description = lib.mdDoc ''
+          Reference to the `matrix-synapse` wrapper with all extras
+          (e.g. for `oidc` or `saml2`) added to the `PYTHONPATH` of all executables.
+
+          This option is useful to reference the "final" `matrix-synapse` package that's
+          actually used by `matrix-synapse.service`. For instance, when using
+          workers, it's possible to run
+          `''${config.services.matrix-synapse.package}/bin/synapse_worker` and
+          no additional PYTHONPATH needs to be specified for extras or plugins configured
+          via `services.matrix-synapse`.
+
+          However, this means that this option is supposed to be only declared
+          by the `services.matrix-synapse` module itself and is thus read-only.
+          In order to modify `matrix-synapse` itself, use an overlay to override
+          `pkgs.matrix-synapse-unwrapped`.
+        '';
+      };
+
+      extras = mkOption {
+        type = types.listOf (types.enum (lib.attrNames pkgs.matrix-synapse-unwrapped.optional-dependencies));
+        default = defaultExtras;
+        example = literalExpression ''
+          [
+            "cache-memory" # Provide statistics about caching memory consumption
+            "jwt"          # JSON Web Token authentication
+            "opentracing"  # End-to-end tracing support using Jaeger
+            "oidc"         # OpenID Connect authentication
+            "postgres"     # PostgreSQL database backend
+            "redis"        # Redis support for the replication stream between worker processes
+            "saml2"        # SAML2 authentication
+            "sentry"       # Error tracking and performance metrics
+            "systemd"      # Provide the JournalHandler used in the default log_config
+            "url-preview"  # Support for oEmbed URL previews
+            "user-search"  # Support internationalized domain names in user-search
+          ]
+        '';
         description = lib.mdDoc ''
-          Overridable attribute of the matrix synapse server package to use.
+          Explicitly install extras provided by matrix-synapse. Most
+          will require some additional configuration.
+
+          Extras will automatically be enabled, when the relevant
+          configuration sections are present.
+
+          Please note that this option is additive: i.e. when adding a new item
+          to this list, the defaults are still kept. To override the defaults as well,
+          use `lib.mkForce`.
         '';
       };
 
@@ -193,7 +254,7 @@ in {
         default = {};
         description = mdDoc ''
           The primary synapse configuration. See the
-          [sample configuration](https://github.com/matrix-org/synapse/blob/v${cfg.package.version}/docs/sample_config.yaml)
+          [sample configuration](https://github.com/matrix-org/synapse/blob/v${pkgs.matrix-synapse-unwrapped.version}/docs/sample_config.yaml)
           for possible values.
 
           Secrets should be passed in by using the `extraConfigFiles` option.
@@ -706,6 +767,10 @@ in {
     ];
 
     services.matrix-synapse.configFile = configFile;
+    services.matrix-synapse.package = wrapped;
+
+    # default them, so they are additive
+    services.matrix-synapse.extras = defaultExtras;
 
     users.users.matrix-synapse = {
       group = "matrix-synapse";
@@ -729,9 +794,7 @@ in {
           --keys-directory ${cfg.dataDir} \
           --generate-keys
       '';
-      environment = {
-        PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ];
-      } // optionalAttrs (cfg.withJemalloc) {
+      environment = optionalAttrs (cfg.withJemalloc) {
         LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
       };
       serviceConfig = {
diff --git a/nixpkgs/nixos/modules/services/misc/gitea.nix b/nixpkgs/nixos/modules/services/misc/gitea.nix
index ec88de6da3ba..f6ef2bb91910 100644
--- a/nixpkgs/nixos/modules/services/misc/gitea.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitea.nix
@@ -666,6 +666,7 @@ in
          USER = cfg.user;
          HOME = cfg.stateDir;
          GITEA_WORK_DIR = cfg.stateDir;
+         GITEA_CUSTOM = cfg.customDir;
        };
 
        serviceConfig = {
diff --git a/nixpkgs/nixos/modules/services/misc/zoneminder.nix b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
index 616a60a123ea..b2e4e760d828 100644
--- a/nixpkgs/nixos/modules/services/misc/zoneminder.nix
+++ b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
@@ -351,7 +351,7 @@ in {
           CacheDirectory = dirs cacheDirs;
           RuntimeDirectory = dirName;
           ReadWriteDirectories = lib.mkIf useCustomDir [ cfg.storageDir ];
-          StateDirectory = dirs (lib.optional (!useCustomDir) libDirs);
+          StateDirectory = dirs (lib.optionals (!useCustomDir) libDirs);
           LogsDirectory = dirName;
           PrivateTmp = true;
           ProtectSystem = "strict";
diff --git a/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix b/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
index 58a0faed962c..1736b0c088a3 100644
--- a/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/datadog-agent.nix
@@ -153,6 +153,18 @@ in {
       type = types.bool;
     };
 
+    processAgentPackage = mkOption {
+      default = pkgs.datadog-process-agent;
+      defaultText = literalExpression "pkgs.datadog-process-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.
+      '';
+      type = types.package;
+    };
+
     enableTraceAgent = mkOption {
       description = lib.mdDoc ''
         Whether to enable the trace agent.
@@ -270,7 +282,7 @@ in {
         path = [ ];
         script = ''
           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
-          ${pkgs.datadog-process-agent}/bin/process-agent --config /etc/datadog-agent/datadog.yaml
+          ${cfg.processAgentPackage}/bin/process-agent --config /etc/datadog-agent/datadog.yaml
         '';
       });
 
diff --git a/nixpkgs/nixos/modules/services/monitoring/netdata.nix b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
index 89a842023c88..3833418b5add 100644
--- a/nixpkgs/nixos/modules/services/monitoring/netdata.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
@@ -214,6 +214,7 @@ in {
         ++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package);
       environment = {
         PYTHONPATH = "${cfg.package}/libexec/netdata/python.d/python_modules";
+        NETDATA_PIPENAME = "/run/netdata/ipc";
       } // lib.optionalAttrs (!cfg.enableAnalyticsReporting) {
         DO_NOT_TRACK = "1";
       };
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
index 397125b51230..f5b97c51186a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -36,6 +36,7 @@ let
     "fastly"
     "fritzbox"
     "graphite"
+    "idrac"
     "influxdb"
     "ipmi"
     "json"
@@ -318,6 +319,14 @@ in
       message = ''
         Scaphandre needs 'intel_rapl_common' kernel module to be enabled. Please add it in 'boot.kernelModules'.
       '';
+    } {
+      assertion = cfg.idrac.enable -> (
+        (cfg.idrac.configurationPath == null) != (cfg.idrac.configuration == null)
+      );
+      message = ''
+        Please ensure you have either `services.prometheus.exporters.idrac.configuration'
+          or `services.prometheus.exporters.idrac.configurationPath' set!
+      '';
     } ] ++ (flip map (attrNames exporterOpts) (exporter: {
       assertion = cfg.${exporter}.firewallFilter != null -> cfg.${exporter}.openFirewall;
       message = ''
@@ -325,7 +334,12 @@ in
         `openFirewall' is set to `true'!
       '';
     })) ++ config.services.prometheus.exporters.assertions;
-    warnings = config.services.prometheus.exporters.warnings;
+    warnings = [(mkIf (config.services.prometheus.exporters.idrac.enable && config.services.prometheus.exporters.idrac.configurationPath != null) ''
+        Configuration file in `services.prometheus.exporters.idrac.configurationPath` may override
+        `services.prometheus.exporters.idrac.listenAddress` and/or `services.prometheus.exporters.idrac.port`.
+        Consider using `services.prometheus.exporters.idrac.configuration` instead.
+      ''
+    )] ++ config.services.prometheus.exporters.warnings;
   }] ++ [(mkIf config.services.minio.enable {
     services.prometheus.exporters.minio.minioAddress  = mkDefault "http://localhost:9000";
     services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey;
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix
new file mode 100644
index 000000000000..f5604bc00ee0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix
@@ -0,0 +1,69 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+let
+  cfg = config.services.prometheus.exporters.idrac;
+
+  configFile = if cfg.configurationPath != null
+               then cfg.configurationPath
+               else pkgs.writeText "idrac.yml" (builtins.toJSON cfg.configuration);
+in
+{
+  port = 9348;
+  extraOpts = {
+    configurationPath = mkOption {
+      type = with types; nullOr path;
+      default = null;
+      example = "/etc/prometheus-idrac-exporter/idrac.yml";
+      description = lib.mdDoc ''
+        Path to the service's config file. This path can either be a computed path in /nix/store or a path in the local filesystem.
+
+        The config file should NOT be stored in /nix/store as it will contain passwords and/or keys in plain text.
+
+        Mutually exclusive with `configuration` option.
+
+        Configuration reference: https://github.com/mrlhansen/idrac_exporter/#configuration
+      '';
+    };
+    configuration = mkOption {
+      type = types.nullOr types.attrs;
+      description = lib.mdDoc ''
+        Configuration for iDRAC exporter, as a nix attribute set.
+
+        Configuration reference: https://github.com/mrlhansen/idrac_exporter/#configuration
+
+        Mutually exclusive with `configurationPath` option.
+      '';
+      default = null;
+      example = {
+        timeout = 10;
+        retries = 1;
+        hosts = {
+          default = {
+            username = "username";
+            password = "password";
+          };
+        };
+        metrics = {
+          system = true;
+          sensors = true;
+          power = true;
+          sel = true;
+          storage = true;
+          memory = true;
+        };
+      };
+    };
+  };
+
+  serviceOpts = {
+    serviceConfig = {
+      LoadCredential = "configFile:${configFile}";
+      ExecStart = "${pkgs.prometheus-idrac-exporter}/bin/idrac_exporter -config %d/configFile";
+      Environment = [
+        "IDRAC_EXPORTER_LISTEN_ADDRESS=${cfg.listenAddress}"
+        "IDRAC_EXPORTER_LISTEN_PORT=${toString cfg.port}"
+      ];
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/eris-server.nix b/nixpkgs/nixos/modules/services/network-filesystems/eris-server.nix
new file mode 100644
index 000000000000..66eccfac408c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/network-filesystems/eris-server.nix
@@ -0,0 +1,103 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.eris-server;
+  stateDirectoryPath = "\${STATE_DIRECTORY}";
+in {
+
+  options.services.eris-server = {
+
+    enable = lib.mkEnableOption "an ERIS server";
+
+    package = lib.mkOption {
+      type = lib.types.package;
+      default = pkgs.eris-go;
+      defaultText = lib.literalExpression "pkgs.eris-go";
+      description = "Package to use for the ERIS server.";
+    };
+
+    decode = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      description = ''
+        Whether the HTTP service (when enabled) will decode ERIS content at /uri-res/N2R?urn:eris:.
+        Enabling this is recommended only for private or local-only servers.
+      '';
+    };
+
+    listenCoap = lib.mkOption {
+      type = lib.types.str;
+      default = ":5683";
+      example = "[::1]:5683";
+      description = ''
+        Server CoAP listen address. Listen on all IP addresses at port 5683 by default.
+        Please note that the server can service client requests for ERIS-blocks by
+        querying other clients connected to the server. Whether or not blocks are
+        relayed back to the server depends on client configuration but be aware this
+        may leak sensitive metadata and trigger network activity.
+      '';
+    };
+
+    listenHttp = lib.mkOption {
+      type = lib.types.str;
+      default = "";
+      example = "[::1]:8080";
+      description = "Server HTTP listen address. Do not listen by default.";
+    };
+
+    backends = lib.mkOption {
+      type = with lib.types; listOf str;
+      description = ''
+        List of backend URLs.
+        Add "get" and "put" as query elements to enable those operations.
+      '';
+      example = [
+        "bolt+file:///srv/eris.bolt?get&put"
+        "coap+tcp://eris.example.com:5683?get"
+      ];
+    };
+
+    mountpoint = lib.mkOption {
+      type = lib.types.str;
+      default = "";
+      example = "/eris";
+      description = ''
+        Mountpoint for FUSE namespace that exposes "urn:eris:…" files.
+      '';
+    };
+
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.eris-server = let
+      cmd =
+        "${cfg.package}/bin/eris-go server --coap '${cfg.listenCoap}' --http '${cfg.listenHttp}' ${
+          lib.optionalString cfg.decode "--decode "
+        }${
+          lib.optionalString (cfg.mountpoint != "")
+          ''--mountpoint "${cfg.mountpoint}" ''
+        }${lib.strings.escapeShellArgs cfg.backends}";
+    in {
+      description = "ERIS block server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = lib.mkIf (cfg.mountpoint != "") ''
+        export PATH=${config.security.wrapperDir}:$PATH
+        ${cmd}
+      '';
+      serviceConfig = let
+        umounter = lib.mkIf (cfg.mountpoint != "")
+          "-${config.security.wrapperDir}/fusermount -uz ${cfg.mountpoint}";
+      in {
+        ExecStartPre = umounter;
+        ExecStart = lib.mkIf (cfg.mountpoint == "") cmd;
+        ExecStopPost = umounter;
+        Restart = "always";
+        RestartSec = 20;
+        AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ ehmry ];
+}
diff --git a/nixpkgs/nixos/modules/services/networking/dae.nix b/nixpkgs/nixos/modules/services/networking/dae.nix
new file mode 100644
index 000000000000..231c555b3303
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/dae.nix
@@ -0,0 +1,41 @@
+{ config, pkgs, lib, ... }:
+let
+  cfg = config.services.dae;
+in
+{
+  meta.maintainers = with lib.maintainers; [ pokon548 ];
+
+  options = {
+    services.dae = {
+      enable = lib.options.mkEnableOption (lib.mdDoc "the dae service");
+      package = lib.mkPackageOptionMD pkgs "dae" { };
+    };
+  };
+
+  config = lib.mkIf config.services.dae.enable {
+    networking.firewall.allowedTCPPorts = [ 12345 ];
+    networking.firewall.allowedUDPPorts = [ 12345 ];
+
+    systemd.services.dae = {
+      unitConfig = {
+        Description = "dae Service";
+        Documentation = "https://github.com/daeuniverse/dae";
+        After = [ "network-online.target" "systemd-sysctl.service" ];
+        Wants = [ "network-online.target" ];
+      };
+
+      serviceConfig = {
+        User = "root";
+        ExecStartPre = "${lib.getExe cfg.package} validate -c /etc/dae/config.dae";
+        ExecStart = "${lib.getExe cfg.package} run --disable-timestamp -c /etc/dae/config.dae";
+        ExecReload = "${lib.getExe cfg.package} reload $MAINPID";
+        LimitNPROC = 512;
+        LimitNOFILE = 1048576;
+        Restart = "on-abnormal";
+        Type = "notify";
+      };
+
+      wantedBy = [ "multi-user.target" ];
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
index 082e0195093e..741f054cd88b 100644
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
@@ -71,9 +71,9 @@ let
     if ! keyValid; then
       echo "certificate soon to become invalid; backing up old cert"
       mkdir -p oldkeys
-      mv -v ${cfg.providerName}.key oldkeys/${cfg.providerName}-$(date +%F-%T).key
-      mv -v ${cfg.providerName}.crt oldkeys/${cfg.providerName}-$(date +%F-%T).crt
-      systemctl restart dnscrypt-wrapper
+      mv -v "${cfg.providerName}.key" "oldkeys/${cfg.providerName}-$(date +%F-%T).key"
+      mv -v "${cfg.providerName}.crt" "oldkeys/${cfg.providerName}-$(date +%F-%T).crt"
+      kill "$(pidof -s dnscrypt-wrapper)"
     fi
   '';
 
@@ -222,17 +222,6 @@ in {
     };
     users.groups.dnscrypt-wrapper = { };
 
-    security.polkit.extraConfig = ''
-      // Allow dnscrypt-wrapper user to restart dnscrypt-wrapper.service
-      polkit.addRule(function(action, subject) {
-          if (action.id == "org.freedesktop.systemd1.manage-units" &&
-              action.lookup("unit") == "dnscrypt-wrapper.service" &&
-              subject.user == "dnscrypt-wrapper") {
-              return polkit.Result.YES;
-          }
-        });
-    '';
-
     systemd.services.dnscrypt-wrapper = {
       description = "dnscrypt-wrapper daemon";
       after    = [ "network.target" ];
@@ -242,7 +231,7 @@ in {
       serviceConfig = {
         User = "dnscrypt-wrapper";
         WorkingDirectory = dataDir;
-        Restart   = "on-failure";
+        Restart   = "always";
         ExecStart = "${pkgs.dnscrypt-wrapper}/bin/dnscrypt-wrapper ${toString daemonArgs}";
       };
 
@@ -255,7 +244,7 @@ in {
       requires = [ "dnscrypt-wrapper.service" ];
       description = "Rotates DNSCrypt wrapper keys if soon to expire";
 
-      path   = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy1 gawk ];
+      path   = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy1 gawk procps ];
       script = rotateKeys;
       serviceConfig.User = "dnscrypt-wrapper";
     };
diff --git a/nixpkgs/nixos/modules/services/networking/haproxy.nix b/nixpkgs/nixos/modules/services/networking/haproxy.nix
index e0b686434b6e..208eb356d629 100644
--- a/nixpkgs/nixos/modules/services/networking/haproxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/haproxy.nix
@@ -17,14 +17,9 @@ with lib;
   options = {
     services.haproxy = {
 
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = lib.mdDoc ''
-          Whether to enable HAProxy, the reliable, high performance TCP/HTTP
-          load balancer.
-        '';
-      };
+      enable = mkEnableOption (lib.mdDoc "HAProxy, the reliable, high performance TCP/HTTP load balancer.");
+
+      package = mkPackageOptionMD pkgs "haproxy" { };
 
       user = mkOption {
         type = types.str;
@@ -70,15 +65,15 @@ with lib;
         ExecStartPre = [
           # when the master process receives USR2, it reloads itself using exec(argv[0]),
           # so we create a symlink there and update it before reloading
-          "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy"
+          "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy"
           # when running the config test, don't be quiet so we can see what goes wrong
           "/run/haproxy/haproxy -c -f ${haproxyCfg}"
         ];
         ExecStart = "/run/haproxy/haproxy -Ws -f /etc/haproxy.cfg -p /run/haproxy/haproxy.pid";
         # support reloading
         ExecReload = [
-          "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}"
-          "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy"
+          "${lib.getExe cfg.package} -c -f ${haproxyCfg}"
+          "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy"
           "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"
         ];
         KillMode = "mixed";
diff --git a/nixpkgs/nixos/modules/services/networking/headscale.nix b/nixpkgs/nixos/modules/services/networking/headscale.nix
index 78253dd9d112..03e6f86af53f 100644
--- a/nixpkgs/nixos/modules/services/networking/headscale.nix
+++ b/nixpkgs/nixos/modules/services/networking/headscale.nix
@@ -292,7 +292,7 @@ in {
               };
 
               client_secret_path = mkOption {
-                type = types.nullOr types.path;
+                type = types.nullOr types.str;
                 default = null;
                 description = lib.mdDoc ''
                   Path to OpenID Connect client secret file. Expands environment variables in format ''${VAR}.
diff --git a/nixpkgs/nixos/modules/services/networking/hostapd.nix b/nixpkgs/nixos/modules/services/networking/hostapd.nix
index 924abfc2953f..4ec066c2ec97 100644
--- a/nixpkgs/nixos/modules/services/networking/hostapd.nix
+++ b/nixpkgs/nixos/modules/services/networking/hostapd.nix
@@ -987,7 +987,7 @@ in {
                   } // optionalAttrs (bssCfg.authentication.wpaPassword != null) {
                     wpa_passphrase = bssCfg.authentication.wpaPassword;
                   } // optionalAttrs (bssCfg.authentication.wpaPskFile != null) {
-                    wpa_psk_file = bssCfg.authentication.wpaPskFile;
+                    wpa_psk_file = toString bssCfg.authentication.wpaPskFile;
                   };
 
                   dynamicConfigScripts = let
diff --git a/nixpkgs/nixos/modules/services/networking/jool.nix b/nixpkgs/nixos/modules/services/networking/jool.nix
new file mode 100644
index 000000000000..3aafbe40967c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/jool.nix
@@ -0,0 +1,222 @@
+{ config, pkgs, lib, ... }:
+
+let
+  cfg = config.networking.jool;
+
+  jool = config.boot.kernelPackages.jool;
+  jool-cli = pkgs.jool-cli;
+
+  hardening = {
+    # Run as unprivileged user
+    User = "jool";
+    Group = "jool";
+    DynamicUser = true;
+
+    # Restrict filesystem to only read the jool module
+    TemporaryFileSystem = [ "/" ];
+    BindReadOnlyPaths = [
+      builtins.storeDir
+      "/run/current-system/kernel-modules"
+    ];
+
+    # Give capabilities to load the module and configure it
+    AmbientCapabilities = [ "CAP_SYS_MODULE" "CAP_NET_ADMIN" ];
+    RestrictAddressFamilies = [ "AF_NETLINK" ];
+
+    # Other restrictions
+    RestrictNamespaces = [ "net" ];
+    SystemCallFilter = [ "@system-service" "@module" ];
+    CapabilityBoundingSet = [ "CAP_SYS_MODULE" "CAP_NET_ADMIN" ];
+  };
+
+  configFormat = pkgs.formats.json {};
+
+  mkDefaultAttrs = lib.mapAttrs (n: v: lib.mkDefault v);
+
+  defaultNat64 = {
+    instance = "default";
+    framework = "netfilter";
+    global.pool6 = "64:ff9b::/96";
+  };
+  defaultSiit = {
+    instance = "default";
+    framework = "netfilter";
+  };
+
+  nat64Conf = configFormat.generate "jool-nat64.conf" cfg.nat64.config;
+  siitConf  = configFormat.generate "jool-siit.conf" cfg.siit.config;
+
+in
+
+{
+  ###### interface
+
+  options = {
+    networking.jool.enable = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      relatedPackages = [ "linuxPackages.jool" "jool-cli" ];
+      description = lib.mdDoc ''
+        Whether to enable Jool, an Open Source implementation of IPv4/IPv6
+        translation on Linux.
+
+        Jool can perform stateless IP/ICMP translation (SIIT) or stateful
+        NAT64, analogous to the IPv4 NAPT. Refer to the upstream
+        [documentation](https://nicmx.github.io/Jool/en/intro-xlat.html) for
+        the supported modes of translation and how to configure them.
+      '';
+    };
+
+    networking.jool.nat64.enable = lib.mkEnableOption (lib.mdDoc "a NAT64 instance of Jool.");
+    networking.jool.nat64.config = lib.mkOption {
+      type = configFormat.type;
+      default = defaultNat64;
+      example = lib.literalExpression ''
+        {
+          # custom NAT64 prefix
+          global.pool6 = "2001:db8:64::/96";
+
+          # Port forwarding
+          bib = [
+            { # SSH 192.0.2.16 → 2001:db8:a::1
+              "protocol"     = "TCP";
+              "ipv4 address" = "192.0.2.16#22";
+              "ipv6 address" = "2001:db8:a::1#22";
+            }
+            { # DNS (TCP) 192.0.2.16 → 2001:db8:a::2
+              "protocol"     = "TCP";
+              "ipv4 address" = "192.0.2.16#53";
+              "ipv6 address" = "2001:db8:a::2#53";
+            }
+            { # DNS (UDP) 192.0.2.16 → 2001:db8:a::2
+              "protocol" = "UDP";
+              "ipv4 address" = "192.0.2.16#53";
+              "ipv6 address" = "2001:db8:a::2#53";
+            }
+          ];
+
+          pool4 = [
+            # Ports for dynamic translation
+            { protocol =  "TCP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
+            { protocol =  "UDP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
+            { protocol = "ICMP";  prefix = "192.0.2.16/32"; "port range" = "40001-65535"; }
+
+            # Ports for static BIB entries
+            { protocol =  "TCP";  prefix = "192.0.2.16/32"; "port range" = "22"; }
+            { protocol =  "UDP";  prefix = "192.0.2.16/32"; "port range" = "53"; }
+          ];
+        }
+      '';
+      description = lib.mdDoc ''
+        The configuration of a stateful NAT64 instance of Jool managed through
+        NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
+        available options.
+
+        ::: {.note}
+        Existing or more instances created manually will not interfere with the
+        NixOS instance, provided the respective `pool4` addresses and port
+        ranges are not overlapping.
+        :::
+
+        ::: {.warning}
+        Changes to the NixOS instance performed via `jool instance nixos-nat64`
+        are applied correctly but will be lost after restarting
+        `jool-nat64.service`.
+        :::
+      '';
+    };
+
+    networking.jool.siit.enable = lib.mkEnableOption (lib.mdDoc "a SIIT instance of Jool.");
+    networking.jool.siit.config = lib.mkOption {
+      type = configFormat.type;
+      default = defaultSiit;
+      example = lib.literalExpression ''
+        {
+          # Maps any IPv4 address x.y.z.t to 2001:db8::x.y.z.t and v.v.
+          pool6 = "2001:db8::/96";
+
+          # Explicit address mappings
+          eamt = [
+            # 2001:db8:1:: ←→ 192.0.2.0
+            { "ipv6 prefix": "2001:db8:1::/128", "ipv4 prefix": "192.0.2.0" }
+            # 2001:db8:1::x ←→ 198.51.100.x
+            { "ipv6 prefix": "2001:db8:2::/120", "ipv4 prefix": "198.51.100.0/24" }
+          ]
+        }
+      '';
+      description = lib.mdDoc ''
+        The configuration of a SIIT instance of Jool managed through
+        NixOS. See https://nicmx.github.io/Jool/en/config-atomic.html for the
+        available options.
+
+        ::: {.note}
+        Existing or more instances created manually will not interfere with the
+        NixOS instance, provided the respective `EAMT` address mappings are not
+        overlapping.
+        :::
+
+        ::: {.warning}
+        Changes to the NixOS instance performed via `jool instance nixos-siit`
+        are applied correctly but will be lost after restarting
+        `jool-siit.service`.
+        :::
+      '';
+    };
+
+  };
+
+  ###### implementation
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ jool-cli ];
+    boot.extraModulePackages = [ jool ];
+
+    systemd.services.jool-nat64 = lib.mkIf cfg.nat64.enable {
+      description = "Jool, NAT64 setup";
+      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      reloadIfChanged = true;
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
+        ExecStart    = "${jool-cli}/bin/jool file handle ${nat64Conf}";
+        ExecStop     = "${jool-cli}/bin/jool -f ${nat64Conf} instance remove";
+      } // hardening;
+    };
+
+    systemd.services.jool-siit = lib.mkIf cfg.siit.enable {
+      description = "Jool, SIIT setup";
+      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      reloadIfChanged = true;
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
+        ExecStart    = "${jool-cli}/bin/jool_siit file handle ${siitConf}";
+        ExecStop     = "${jool-cli}/bin/jool_siit -f ${siitConf} instance remove";
+      } // hardening;
+    };
+
+    system.checks = lib.singleton (pkgs.runCommand "jool-validated" {
+      nativeBuildInputs = [ pkgs.buildPackages.jool-cli ];
+      preferLocalBuild = true;
+    } ''
+      printf 'Validating Jool configuration... '
+      ${lib.optionalString cfg.siit.enable "jool_siit file check ${siitConf}"}
+      ${lib.optionalString cfg.nat64.enable "jool file check ${nat64Conf}"}
+      printf 'ok\n'
+      touch "$out"
+    '');
+
+    networking.jool.nat64.config = mkDefaultAttrs defaultNat64;
+    networking.jool.siit.config  = mkDefaultAttrs defaultSiit;
+
+  };
+
+  meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
index 2d421abc8be7..afd721e34da5 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/chrony.nix
@@ -27,7 +27,10 @@ let
     ${cfg.extraConfig}
   '';
 
-  chronyFlags = [ "-n" "-m" "-u" "chrony" "-f" "${configFile}" ] ++ cfg.extraFlags;
+  chronyFlags =
+    [ "-n" "-u" "chrony" "-f" "${configFile}" ]
+    ++ optional cfg.enableMemoryLocking "-m"
+    ++ cfg.extraFlags;
 in
 {
   options = {
@@ -73,6 +76,15 @@ in
         '';
       };
 
+      enableMemoryLocking = mkOption {
+        type = types.bool;
+        default = config.environment.memoryAllocator.provider != "graphene-hardened";
+        defaultText = ''config.environment.memoryAllocator.provider != "graphene-hardened"'';
+        description = lib.mdDoc ''
+          Whether to add the `-m` flag to lock memory.
+        '';
+      };
+
       enableNTS = mkOption {
         type = types.bool;
         default = false;
diff --git a/nixpkgs/nixos/modules/services/networking/zerotierone.nix b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
index 0d9e25cfc52c..f78fd8642ba0 100644
--- a/nixpkgs/nixos/modules/services/networking/zerotierone.nix
+++ b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
@@ -13,7 +13,9 @@ in
     example = [ "a8a2c3c10c1a68de" ];
     type = types.listOf types.str;
     description = lib.mdDoc ''
-      List of ZeroTier Network IDs to join on startup
+      List of ZeroTier Network IDs to join on startup.
+      Note that networks are only ever joined, but not automatically left after removing them from the list.
+      To remove networks, use the ZeroTier CLI: `zerotier-cli leave <network-id>`
     '';
   };
 
diff --git a/nixpkgs/nixos/modules/services/security/kanidm.nix b/nixpkgs/nixos/modules/services/security/kanidm.nix
index 6fb9f71a489e..d8a99dee59f4 100644
--- a/nixpkgs/nixos/modules/services/security/kanidm.nix
+++ b/nixpkgs/nixos/modules/services/security/kanidm.nix
@@ -69,6 +69,8 @@ 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" {};
+
     serverSettings = lib.mkOption {
       type = lib.types.submodule {
         freeformType = settingsFormat.type;
@@ -222,7 +224,7 @@ in
         }
       ];
 
-    environment.systemPackages = lib.mkIf cfg.enableClient [ pkgs.kanidm ];
+    environment.systemPackages = lib.mkIf cfg.enableClient [ cfg.package ];
 
     systemd.services.kanidm = lib.mkIf cfg.enableServer {
       description = "kanidm identity management daemon";
@@ -237,7 +239,7 @@ in
           StateDirectory = "kanidm";
           StateDirectoryMode = "0700";
           RuntimeDirectory = "kanidmd";
-          ExecStart = "${pkgs.kanidm}/bin/kanidmd server -c ${serverConfigFile}";
+          ExecStart = "${cfg.package}/bin/kanidmd server -c ${serverConfigFile}";
           User = "kanidm";
           Group = "kanidm";
 
@@ -270,7 +272,7 @@ in
           CacheDirectory = "kanidm-unixd";
           CacheDirectoryMode = "0700";
           RuntimeDirectory = "kanidm-unixd";
-          ExecStart = "${pkgs.kanidm}/bin/kanidm_unixd";
+          ExecStart = "${cfg.package}/bin/kanidm_unixd";
           User = "kanidm-unixd";
           Group = "kanidm-unixd";
 
@@ -302,7 +304,7 @@ in
       partOf = [ "kanidm-unixd.service" ];
       restartTriggers = [ unixConfigFile clientConfigFile ];
       serviceConfig = {
-        ExecStart = "${pkgs.kanidm}/bin/kanidm_unixd_tasks";
+        ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks";
 
         BindReadOnlyPaths = [
           "/nix/store"
@@ -346,7 +348,7 @@ in
       })
     ];
 
-    system.nssModules = lib.mkIf cfg.enablePam [ pkgs.kanidm ];
+    system.nssModules = lib.mkIf cfg.enablePam [ cfg.package ];
 
     system.nssDatabases.group = lib.optional cfg.enablePam "kanidm";
     system.nssDatabases.passwd = lib.optional cfg.enablePam "kanidm";
@@ -365,7 +367,7 @@ in
           description = "Kanidm server";
           isSystemUser = true;
           group = "kanidm";
-          packages = with pkgs; [ kanidm ];
+          packages = [ cfg.package ];
         };
       })
       (lib.mkIf cfg.enablePam {
diff --git a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
index 12547acabfe0..718c3d2498ea 100644
--- a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
@@ -579,7 +579,7 @@ in
       description = "OAuth2 Proxy";
       path = [ cfg.package ];
       wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
+      after = [ "network-online.target" ];
 
       serviceConfig = {
         User = "oauth2_proxy";
diff --git a/nixpkgs/nixos/modules/services/security/opensnitch.nix b/nixpkgs/nixos/modules/services/security/opensnitch.nix
index 98695b1ef060..013aeb16756c 100644
--- a/nixpkgs/nixos/modules/services/security/opensnitch.nix
+++ b/nixpkgs/nixos/modules/services/security/opensnitch.nix
@@ -147,7 +147,7 @@ in {
   config = mkIf cfg.enable {
 
     # pkg.opensnitch is referred to elsewhere in the module so we don't need to worry about it being garbage collected
-    services.opensnitch.settings = mapAttrs (_: v: mkDefault v) (builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile "${pkgs.opensnitch}/etc/default-config.json")));
+    services.opensnitch.settings = mapAttrs (_: v: mkDefault v) (builtins.fromJSON (builtins.unsafeDiscardStringContext (builtins.readFile "${pkgs.opensnitch}/etc/opensnitchd/default-config.json")));
 
     systemd = {
       packages = [ pkgs.opensnitch ];
@@ -171,9 +171,19 @@ in {
       ${concatMapStrings ({ file, local }: ''
         ln -sf '${file}' "${local}"
       '') rules}
+
+      if [ ! -f /etc/opensnitch-system-fw.json ]; then
+        cp "${pkgs.opensnitch}/etc/opensnitchd/system-fw.json" "/etc/opensnitchd/system-fw.json"
+      fi
     '');
 
-    environment.etc."opensnitchd/default-config.json".source = format.generate "default-config.json" cfg.settings;
+    environment.etc = mkMerge [ ({
+      "opensnitchd/default-config.json".source = format.generate "default-config.json" cfg.settings;
+    }) (mkIf (cfg.settings.ProcMonitorMethod == "ebpf") {
+      "opensnitchd/opensnitch.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch.o";
+      "opensnitchd/opensnitch-dns.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-dns.o";
+      "opensnitchd/opensnitch-procs.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-procs.o";
+    })];
 
   };
 }
diff --git a/nixpkgs/nixos/modules/services/tracing/tempo.nix b/nixpkgs/nixos/modules/services/tracing/tempo.nix
index 4a098c31effe..0b9ca2398b16 100644
--- a/nixpkgs/nixos/modules/services/tracing/tempo.nix
+++ b/nixpkgs/nixos/modules/services/tracing/tempo.nix
@@ -27,6 +27,18 @@ in {
         Specify a path to a configuration file that Tempo should use.
       '';
     };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = lib.literalExpression
+        ''
+          [ "-config.expand-env=true" ]
+        '';
+      description = lib.mdDoc ''
+        Additional flags to pass to the `ExecStart=` in `tempo.service`.
+      '';
+    };
   };
 
   config = mkIf cfg.enable {
@@ -54,7 +66,7 @@ in {
                else cfg.configFile;
       in
       {
-        ExecStart = "${pkgs.tempo}/bin/tempo --config.file=${conf}";
+        ExecStart = "${pkgs.tempo}/bin/tempo --config.file=${conf} ${lib.escapeShellArgs cfg.extraFlags}";
         DynamicUser = true;
         Restart = "always";
         ProtectSystem = "full";
diff --git a/nixpkgs/nixos/modules/services/video/mediamtx.nix b/nixpkgs/nixos/modules/services/video/mediamtx.nix
index 18a9e3d5fe30..c3abd9cdcc5c 100644
--- a/nixpkgs/nixos/modules/services/video/mediamtx.nix
+++ b/nixpkgs/nixos/modules/services/video/mediamtx.nix
@@ -1,79 +1,66 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.services.mediamtx;
-  package = pkgs.mediamtx;
   format = pkgs.formats.yaml {};
 in
 {
+  meta.maintainers = with lib.maintainers; [ fpletz ];
+
   options = {
     services.mediamtx = {
-      enable = mkEnableOption (lib.mdDoc "MediaMTX");
+      enable = lib.mkEnableOption (lib.mdDoc "MediaMTX");
 
-      settings = mkOption {
+      package = lib.mkPackageOptionMD pkgs "mediamtx" { };
+
+      settings = lib.mkOption {
         description = lib.mdDoc ''
-          Settings for MediaMTX.
-          Read more at <https://github.com/aler9/mediamtx/blob/main/mediamtx.yml>
+          Settings for MediaMTX. Refer to the defaults at
+          <https://github.com/bluenviron/mediamtx/blob/main/mediamtx.yml>.
         '';
         type = format.type;
-
-        default = {
-          logLevel = "info";
-          logDestinations = [
-            "stdout"
-          ];
-          # we set this so when the user uses it, it just works (see LogsDirectory below). but it's not used by default.
-          logFile = "/var/log/mediamtx/mediamtx.log";
-        };
-
+        default = {};
         example = {
           paths = {
             cam = {
-              runOnInit = "ffmpeg -f v4l2 -i /dev/video0 -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH";
+              runOnInit = "\${lib.getExe pkgs.ffmpeg} -f v4l2 -i /dev/video0 -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH";
               runOnInitRestart = true;
             };
           };
         };
       };
 
-      env = mkOption {
-        type = with types; attrsOf anything;
+      env = lib.mkOption {
+        type = with lib.types; attrsOf anything;
         description = lib.mdDoc "Extra environment variables for MediaMTX";
         default = {};
         example = {
           MTX_CONFKEY = "mykey";
         };
       };
+
+      allowVideoAccess = lib.mkEnableOption (lib.mdDoc ''
+        Enable access to video devices like cameras on the system.
+      '');
     };
   };
 
-  config = mkIf (cfg.enable) {
+  config = lib.mkIf cfg.enable {
     # NOTE: mediamtx watches this file and automatically reloads if it changes
     environment.etc."mediamtx.yaml".source = format.generate "mediamtx.yaml" cfg.settings;
 
     systemd.services.mediamtx = {
-      environment = cfg.env;
-
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      path = with pkgs; [
-        ffmpeg
-      ];
+      environment = cfg.env;
 
       serviceConfig = {
         DynamicUser = true;
         User = "mediamtx";
         Group = "mediamtx";
-
-        LogsDirectory = "mediamtx";
-
-        # user likely may want to stream cameras, can't hurt to add video group
-        SupplementaryGroups = "video";
-
-        ExecStart = "${package}/bin/mediamtx /etc/mediamtx.yaml";
+        SupplementaryGroups = lib.mkIf cfg.allowVideoAccess "video";
+        ExecStart = "${cfg.package}/bin/mediamtx /etc/mediamtx.yaml";
       };
     };
   };
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.nix b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
index 688367cafaf5..b0d3c44cea81 100644
--- a/nixpkgs/nixos/modules/services/web-apps/grocy.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
@@ -115,10 +115,8 @@ in {
       user = "grocy";
       group = "nginx";
 
-      # PHP 8.0 is the only version which is supported/tested by upstream:
-      # https://github.com/grocy/grocy/blob/v3.3.0/README.md#how-to-install
-      # Compatibility with PHP 8.1 is available on their development branch:
-      # https://github.com/grocy/grocy/commit/38a4ad8ec480c29a1bff057b3482fd103b036848
+      # PHP 8.1 is the only version which is supported/tested by upstream:
+      # https://github.com/grocy/grocy/blob/v4.0.0/README.md#platform-support
       phpPackage = pkgs.php81;
 
       inherit (cfg.phpfpm) settings;
@@ -168,7 +166,7 @@ in {
   };
 
   meta = {
-    maintainers = with maintainers; [ ma27 ];
+    maintainers = with maintainers; [ n0emis ];
     doc = ./grocy.md;
   };
 }
diff --git a/nixpkgs/nixos/modules/services/web-apps/invidious.nix b/nixpkgs/nixos/modules/services/web-apps/invidious.nix
index 8823da010014..5603ef7392e8 100644
--- a/nixpkgs/nixos/modules/services/web-apps/invidious.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/invidious.nix
@@ -7,6 +7,9 @@ let
 
   settingsFile = settingsFormat.generate "invidious-settings" cfg.settings;
 
+  generatedHmacKeyFile = "/var/lib/invidious/hmac_key";
+  generateHmac = cfg.hmacKeyFile == null;
+
   serviceConfig = {
     systemd.services.invidious = {
       description = "Invidious (An alternative YouTube front-end)";
@@ -14,22 +17,47 @@ let
       after = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      script =
-        let
-          jqFilter = "."
-            + lib.optionalString (cfg.database.host != null) "[0].db.password = \"'\"'\"$(cat ${lib.escapeShellArg cfg.database.passwordFile})\"'\"'\""
-            + " | .[0]"
-            + lib.optionalString (cfg.extraSettingsFile != null) " * .[1]";
-          jqFiles = [ settingsFile ] ++ lib.optional (cfg.extraSettingsFile != null) cfg.extraSettingsFile;
-        in
-        ''
-          export INVIDIOUS_CONFIG="$(${pkgs.jq}/bin/jq -s "${jqFilter}" ${lib.escapeShellArgs jqFiles})"
-          exec ${cfg.package}/bin/invidious
-        '';
+      preStart = lib.optionalString generateHmac ''
+        if [[ ! -e "${generatedHmacKeyFile}" ]]; then
+          ${pkgs.pwgen}/bin/pwgen 20 1 > "${generatedHmacKeyFile}"
+          chmod 0600 "${generatedHmacKeyFile}"
+        fi
+      '';
+
+      script = ''
+        configParts=()
+      ''
+      # autogenerated hmac_key
+      + lib.optionalString generateHmac ''
+        configParts+=("$(${pkgs.jq}/bin/jq -R '{"hmac_key":.}' <"${generatedHmacKeyFile}")")
+      ''
+      # generated settings file
+      + ''
+        configParts+=("$(< ${lib.escapeShellArg settingsFile})")
+      ''
+      # optional database password file
+      + lib.optionalString (cfg.database.host != null) ''
+        configParts+=("$(${pkgs.jq}/bin/jq -R '{"db":{"password":.}}' ${lib.escapeShellArg cfg.database.passwordFile})")
+      ''
+      # optional extra settings file
+      + lib.optionalString (cfg.extraSettingsFile != null) ''
+        configParts+=("$(< ${lib.escapeShellArg cfg.extraSettingsFile})")
+      ''
+      # explicitly specified hmac key file
+      + lib.optionalString (cfg.hmacKeyFile != null) ''
+        configParts+=("$(< ${lib.escapeShellArg cfg.hmacKeyFile})")
+      ''
+      # merge all parts into a single configuration with later elements overriding previous elements
+      + ''
+        export INVIDIOUS_CONFIG="$(${pkgs.jq}/bin/jq -s 'reduce .[] as $item ({}; . * $item)' <<<"''${configParts[*]}")"
+        exec ${cfg.package}/bin/invidious
+      '';
 
       serviceConfig = {
         RestartSec = "2s";
         DynamicUser = true;
+        StateDirectory = "invidious";
+        StateDirectoryMode = "0750";
 
         CapabilityBoundingSet = "";
         PrivateDevices = true;
@@ -171,6 +199,18 @@ in
       '';
     };
 
+    hmacKeyFile = lib.mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = lib.mdDoc ''
+        A path to a file containing the `hmac_key`. If `null`, a key will be generated automatically on first
+        start.
+
+        If non-`null`, this option overrides any `hmac_key` specified in {option}`services.invidious.settings` or
+        via {option}`services.invidious.extraSettingsFile`.
+      '';
+    };
+
     extraSettingsFile = lib.mkOption {
       type = types.nullOr types.str;
       default = null;
diff --git a/nixpkgs/nixos/modules/services/web-apps/lemmy.nix b/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
index 6dfba907fb5d..895f3a9f1b4b 100644
--- a/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/lemmy.nix
@@ -160,6 +160,10 @@ in
               root * ${cfg.ui.package}/dist
               file_server
             }
+            handle_path /static/undefined/* {
+              root * ${cfg.ui.package}/dist
+              file_server
+            }
             @for_backend {
               path /api/* /pictrs/* /feeds/* /nodeinfo/*
             }
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index 503db124635c..e0a7e7d4859c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -405,7 +405,11 @@ in {
       adminuser = mkOption {
         type = types.str;
         default = "root";
-        description = lib.mdDoc "Username for the admin account.";
+        description = lib.mdDoc ''
+          Username for the admin account. The username is only set during the
+          initial setup of Nextcloud! Since the username also acts as unique
+          ID internally, it cannot be changed later!
+        '';
       };
       adminpassFile = 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 d5ca6014780a..423ad5375baa 100644
--- a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
@@ -123,7 +123,7 @@ in
         RestrictNamespaces = true;
         RestrictRealtime = true;
         SystemCallArchitectures = "native";
-        SystemCallFilter = [ "@system-service" "~@privileged @setuid @keyring" ];
+        SystemCallFilter = [ "@system-service" "~@setuid @keyring" ];
         UMask = "0066";
       } // lib.optionalAttrs (cfg.port < 1024) {
         AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
diff --git a/nixpkgs/nixos/modules/services/web-servers/minio.nix b/nixpkgs/nixos/modules/services/web-servers/minio.nix
index 21bec4f63a87..0bc7421a0e32 100644
--- a/nixpkgs/nixos/modules/services/web-servers/minio.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/minio.nix
@@ -30,8 +30,8 @@ in
 
     dataDir = mkOption {
       default = [ "/var/lib/minio/data" ];
-      type = types.listOf types.path;
-      description = lib.mdDoc "The list of data directories for storing the objects. Use one path for regular operation and the minimum of 4 endpoints for Erasure Code mode.";
+      type = types.listOf (types.either types.path types.str);
+      description = lib.mdDoc "The list of data directories or nodes for storing the objects. Use one path for regular operation and the minimum of 4 endpoints for Erasure Code mode.";
     };
 
     configDir = mkOption {
@@ -99,7 +99,7 @@ in
     systemd = lib.mkMerge [{
       tmpfiles.rules = [
         "d '${cfg.configDir}' - minio minio - -"
-      ] ++ (map (x: "d '" + x + "' - minio minio - - ") cfg.dataDir);
+      ] ++ (map (x: "d '" + x + "' - minio minio - - ") (builtins.filter lib.types.path.check cfg.dataDir));
 
       services.minio = {
         description = "Minio Object Storage";
diff --git a/nixpkgs/nixos/modules/services/web-servers/rustus.nix b/nixpkgs/nixos/modules/services/web-servers/rustus.nix
index 95c9a6455579..878d790e3666 100644
--- a/nixpkgs/nixos/modules/services/web-servers/rustus.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/rustus.nix
@@ -226,6 +226,10 @@ in
       serviceConfig = {
         ExecStart = "${pkgs.rustus}/bin/rustus";
         StateDirectory = "rustus";
+        # User name is defined here to enable restoring a backup for example
+        # You will run the backup restore command as sudo -u rustus in order
+        # to have write permissions to /var/lib
+        User = "rustus";
         DynamicUser = true;
         LoadCredential = lib.optionals isHybridS3 [
           "S3_ACCESS_KEY_PATH:${cfg.storage.s3_access_key_file}"
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
index a734bc288c9f..bee627ec76c0 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -237,6 +237,11 @@ in {
       budgie.budgie-control-center
     ];
 
+    # Register packages for udev.
+    services.udev.packages = with pkgs; [
+      budgie.magpie
+    ];
+
     # Shell integration for MATE Terminal.
     programs.bash.vteIntegration = true;
     programs.zsh.vteIntegration = true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
index b3cbe4c324df..bb42c52b69ca 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/cinnamon.nix
@@ -212,10 +212,12 @@ in
       programs.bash.vteIntegration = mkDefault true;
       programs.zsh.vteIntegration = mkDefault true;
 
-      # Harmonize Qt applications under Cinnamon
-      qt.enable = true;
-      qt.platformTheme = "gnome";
-      qt.style = "adwaita";
+      # Qt application style
+      qt = {
+        enable = mkDefault true;
+        style = mkDefault "gtk2";
+        platformTheme = mkDefault "gtk2";
+      };
 
       # Default Fonts
       fonts.packages = with pkgs; [
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
index 5d950f7d7fc5..fecdd86deb86 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix
@@ -352,13 +352,6 @@ in
         })
       ];
 
-      # Harmonize Qt application style and also make them use the portal for file chooser dialog.
-      qt = {
-        enable = mkDefault true;
-        platformTheme = mkDefault "gnome";
-        style = mkDefault "adwaita";
-      };
-
       networking.networkmanager.enable = mkDefault true;
 
       services.xserver.updateDbusEnvironment = true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
index d8a47e93afc7..eef7aa14057e 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -200,7 +200,6 @@ in
         gtk3.out # for gtk-launch program
         onboard
         orca # elementary/greeter#668
-        qgnomeplatform
         sound-theme-freedesktop
         xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
       ]) ++ (with pkgs.pantheon; [
@@ -260,10 +259,10 @@ in
       programs.bash.vteIntegration = mkDefault true;
       programs.zsh.vteIntegration = mkDefault true;
 
-      # Harmonize Qt applications under Pantheon
-      qt.enable = true;
-      qt.platformTheme = "gnome";
-      qt.style = "adwaita";
+      # Use native GTK file chooser on Qt apps. This is because Qt does not know Pantheon.
+      # https://invent.kde.org/qt/qt/qtbase/-/blob/6.6/src/gui/platform/unix/qgenericunixthemes.cpp#L1312
+      # https://github.com/elementary/default-settings/blob/7.0.2/profile.d/qt-qpa-platformtheme.sh
+      environment.variables.QT_QPA_PLATFORMTHEME = mkDefault "gtk3";
 
       # Default Fonts
       fonts.packages = with pkgs; [
diff --git a/nixpkgs/nixos/modules/services/x11/picom.nix b/nixpkgs/nixos/modules/services/x11/picom.nix
index 1d6f3daa4022..3df0ea9e60bb 100644
--- a/nixpkgs/nixos/modules/services/x11/picom.nix
+++ b/nixpkgs/nixos/modules/services/x11/picom.nix
@@ -61,6 +61,8 @@ in {
       '';
     };
 
+    package = mkPackageOptionMD pkgs "picom" { };
+
     fade = mkOption {
       type = types.bool;
       default = false;
@@ -301,13 +303,13 @@ in {
       };
 
       serviceConfig = {
-        ExecStart = "${pkgs.picom}/bin/picom --config ${configFile}";
+        ExecStart = "${getExe cfg.package} --config ${configFile}";
         RestartSec = 3;
         Restart = "always";
       };
     };
 
-    environment.systemPackages = [ pkgs.picom ];
+    environment.systemPackages = [ cfg.package ];
   };
 
   meta.maintainers = with lib.maintainers; [ rnhmjoj ];
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
index 1881826944aa..e114f2e26b17 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
@@ -24,7 +24,7 @@ in
             patches = [
               (super.fetchpatch {
                 url = "https://dwm.suckless.org/patches/steam/dwm-steam-6.2.diff";
-                sha256 = "1ld1z3fh6p5f8gr62zknx3axsinraayzxw3rz1qwg73mx2zk5y1f";
+                sha256 = "sha256-f3lffBjz7+0Khyn9c9orzReoLTqBb/9gVGshYARGdVc=";
               })
             ];
           })
diff --git a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
index cfad64039868..04d90968c4c1 100755
--- a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
@@ -253,16 +253,24 @@ sub parse_systemd_ini {
 # If a directory with the same basename ending in .d exists next to the unit file, it will be
 # assumed to contain override files which will be parsed as well and handled properly.
 sub parse_unit {
-    my ($unit_path) = @_;
+    my ($unit_path, $base_unit_path) = @_;
 
     # Parse the main unit and all overrides
     my %unit_data;
     # Replace \ with \\ so glob() still works with units that have a \ in them
     # Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\"
+    $base_unit_path =~ s/\\/\\\\/gmsx;
     $unit_path =~ s/\\/\\\\/gmsx;
-    foreach (glob("${unit_path}{,.d/*.conf}")) {
+
+    foreach (glob("${base_unit_path}{,.d/*.conf}")) {
         parse_systemd_ini(\%unit_data, "$_")
     }
+    # Handle drop-in template-unit instance overrides
+    if ($unit_path ne $base_unit_path) {
+        foreach (glob("${unit_path}.d/*.conf")) {
+            parse_systemd_ini(\%unit_data, "$_")
+        }
+    }
     return %unit_data;
 }
 
@@ -423,7 +431,7 @@ sub compare_units { ## no critic(Subroutines::ProhibitExcessComplexity)
 # Called when a unit exists in both the old systemd and the new system and the units
 # differ. This figures out of what units are to be stopped, restarted, reloaded, started, and skipped.
 sub handle_modified_unit { ## no critic(Subroutines::ProhibitManyArgs, Subroutines::ProhibitExcessComplexity)
-    my ($unit, $base_name, $new_unit_file, $new_unit_info, $active_cur, $units_to_stop, $units_to_start, $units_to_reload, $units_to_restart, $units_to_skip) = @_;
+    my ($unit, $base_name, $new_unit_file, $new_base_unit_file, $new_unit_info, $active_cur, $units_to_stop, $units_to_start, $units_to_reload, $units_to_restart, $units_to_skip) = @_;
 
     if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.path$/msx || $unit =~ /\.slice$/msx) {
         # Do nothing.  These cannot be restarted directly.
@@ -442,7 +450,7 @@ sub handle_modified_unit { ## no critic(Subroutines::ProhibitManyArgs, Subroutin
         # Revert of the attempt: https://github.com/NixOS/nixpkgs/pull/147609
         # More details: https://github.com/NixOS/nixpkgs/issues/74899#issuecomment-981142430
     } else {
-        my %new_unit_info = $new_unit_info ? %{$new_unit_info} : parse_unit($new_unit_file);
+        my %new_unit_info = $new_unit_info ? %{$new_unit_info} : parse_unit($new_unit_file, $new_base_unit_file);
         if (parse_systemd_bool(\%new_unit_info, "Service", "X-ReloadIfChanged", 0) and not $units_to_restart->{$unit} and not $units_to_stop->{$unit}) {
             $units_to_reload->{$unit} = 1;
             record_unit($reload_list_file, $unit);
@@ -538,31 +546,33 @@ my %units_to_filter; # units not shown
 
 my $active_cur = get_active_units();
 while (my ($unit, $state) = each(%{$active_cur})) {
-    my $base_unit = $unit;
+    my $cur_unit_file = "/etc/systemd/system/$unit";
+    my $new_unit_file = "$toplevel/etc/systemd/system/$unit";
 
-    my $cur_unit_file = "/etc/systemd/system/$base_unit";
-    my $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+    my $base_unit = $unit;
+    my $cur_base_unit_file = $cur_unit_file;
+    my $new_base_unit_file = $new_unit_file;
 
     # Detect template instances.
     if (!-e $cur_unit_file && !-e $new_unit_file && $unit =~ /^(.*)@[^\.]*\.(.*)$/msx) {
       $base_unit = "$1\@.$2";
-      $cur_unit_file = "/etc/systemd/system/$base_unit";
-      $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+      $cur_base_unit_file = "/etc/systemd/system/$base_unit";
+      $new_base_unit_file = "$toplevel/etc/systemd/system/$base_unit";
     }
 
     my $base_name = $base_unit;
     $base_name =~ s/\.[[:lower:]]*$//msx;
 
-    if (-e $cur_unit_file && ($state->{state} eq "active" || $state->{state} eq "activating")) {
-        if (! -e $new_unit_file || abs_path($new_unit_file) eq "/dev/null") {
-            my %cur_unit_info = parse_unit($cur_unit_file);
+    if (-e $cur_base_unit_file && ($state->{state} eq "active" || $state->{state} eq "activating")) {
+        if (! -e $new_base_unit_file || abs_path($new_base_unit_file) eq "/dev/null") {
+            my %cur_unit_info = parse_unit($cur_unit_file, $cur_base_unit_file);
             if (parse_systemd_bool(\%cur_unit_info, "Unit", "X-StopOnRemoval", 1)) {
                 $units_to_stop{$unit} = 1;
             }
         }
 
         elsif ($unit =~ /\.target$/msx) {
-            my %new_unit_info = parse_unit($new_unit_file);
+            my %new_unit_info = parse_unit($new_unit_file, $new_base_unit_file);
 
             # Cause all active target units to be restarted below.
             # This should start most changed units we stop here as
@@ -596,11 +606,11 @@ while (my ($unit, $state) = each(%{$active_cur})) {
         }
 
         else {
-            my %cur_unit_info = parse_unit($cur_unit_file);
-            my %new_unit_info = parse_unit($new_unit_file);
+            my %cur_unit_info = parse_unit($cur_unit_file, $cur_base_unit_file);
+            my %new_unit_info = parse_unit($new_unit_file, $new_base_unit_file);
             my $diff = compare_units(\%cur_unit_info, \%new_unit_info);
             if ($diff == 1) {
-                handle_modified_unit($unit, $base_name, $new_unit_file, \%new_unit_info, $active_cur, \%units_to_stop, \%units_to_start, \%units_to_reload, \%units_to_restart, \%units_to_skip);
+                handle_modified_unit($unit, $base_name, $new_unit_file, $new_base_unit_file, \%new_unit_info, $active_cur, \%units_to_stop, \%units_to_start, \%units_to_reload, \%units_to_restart, \%units_to_skip);
             } elsif ($diff == 2 and not $units_to_restart{$unit}) {
                 $units_to_reload{$unit} = 1;
                 record_unit($reload_list_file, $unit);
@@ -710,13 +720,14 @@ if ($action eq "dry-activate") {
     # Handle the activation script requesting the restart or reload of a unit.
     foreach (split(/\n/msx, read_file($dry_restart_by_activation_file, err_mode => "quiet") // "")) {
         my $unit = $_;
+        my $new_unit_file = "$toplevel/etc/systemd/system/$unit";
         my $base_unit = $unit;
-        my $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+        my $new_base_unit_file = $new_unit_file;
 
         # Detect template instances.
         if (!-e $new_unit_file && $unit =~ /^(.*)@[^\.]*\.(.*)$/msx) {
           $base_unit = "$1\@.$2";
-          $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+          $new_base_unit_file = "$toplevel/etc/systemd/system/$base_unit";
         }
 
         my $base_name = $base_unit;
@@ -728,7 +739,7 @@ if ($action eq "dry-activate") {
             next;
         }
 
-        handle_modified_unit($unit, $base_name, $new_unit_file, undef, $active_cur, \%units_to_restart, \%units_to_restart, \%units_to_reload, \%units_to_restart, \%units_to_skip);
+        handle_modified_unit($unit, $base_name, $new_unit_file, $new_base_unit_file, undef, $active_cur, \%units_to_restart, \%units_to_restart, \%units_to_reload, \%units_to_restart, \%units_to_skip);
     }
     unlink($dry_restart_by_activation_file);
 
@@ -782,13 +793,14 @@ system("$out/activate", "$out") == 0 or $res = 2;
 # Handle the activation script requesting the restart or reload of a unit.
 foreach (split(/\n/msx, read_file($restart_by_activation_file, err_mode => "quiet") // "")) {
     my $unit = $_;
+    my $new_unit_file = "$toplevel/etc/systemd/system/$unit";
     my $base_unit = $unit;
-    my $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+    my $new_base_unit_file = $new_unit_file;
 
     # Detect template instances.
     if (!-e $new_unit_file && $unit =~ /^(.*)@[^\.]*\.(.*)$/msx) {
       $base_unit = "$1\@.$2";
-      $new_unit_file = "$toplevel/etc/systemd/system/$base_unit";
+      $new_base_unit_file = "$toplevel/etc/systemd/system/$base_unit";
     }
 
     my $base_name = $base_unit;
@@ -801,7 +813,7 @@ foreach (split(/\n/msx, read_file($restart_by_activation_file, err_mode => "quie
         next;
     }
 
-    handle_modified_unit($unit, $base_name, $new_unit_file, undef, $active_cur, \%units_to_restart, \%units_to_restart, \%units_to_reload, \%units_to_restart, \%units_to_skip);
+    handle_modified_unit($unit, $base_name, $new_unit_file, $new_base_unit_file, undef, $active_cur, \%units_to_restart, \%units_to_restart, \%units_to_reload, \%units_to_restart, \%units_to_skip);
 }
 # We can remove the file now because it has been propagated to the other restart/reload files
 unlink($restart_by_activation_file);
@@ -859,7 +871,7 @@ if (scalar(keys(%units_to_reload)) > 0) {
     for my $unit (keys(%units_to_reload)) {
         if (!unit_is_active($unit)) {
             # Figure out if we need to start the unit
-            my %unit_info = parse_unit("$toplevel/etc/systemd/system/$unit");
+            my %unit_info = parse_unit("$toplevel/etc/systemd/system/$unit", "$toplevel/etc/systemd/system/$unit");
             if (!(parse_systemd_bool(\%unit_info, "Unit", "RefuseManualStart", 0) || parse_systemd_bool(\%unit_info, "Unit", "X-OnlyManualStart", 0))) {
                 $units_to_start{$unit} = 1;
                 record_unit($start_list_file, $unit);
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index 07c2e05ce374..1f9ad570db7d 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -4,38 +4,9 @@ with lib;
 
 let
   systemBuilder =
-    let
-      kernelPath = "${config.boot.kernelPackages.kernel}/" +
-        "${config.system.boot.loader.kernelFile}";
-      initrdPath = "${config.system.build.initialRamdisk}/" +
-        "${config.system.boot.loader.initrdFile}";
-    in ''
+    ''
       mkdir $out
 
-      # Containers don't have their own kernel or initrd.  They boot
-      # directly into stage 2.
-      ${optionalString config.boot.kernel.enable ''
-        if [ ! -f ${kernelPath} ]; then
-          echo "The bootloader cannot find the proper kernel image."
-          echo "(Expecting ${kernelPath})"
-          false
-        fi
-
-        ln -s ${kernelPath} $out/kernel
-        ln -s ${config.system.modulesTree} $out/kernel-modules
-        ${optionalString (config.hardware.deviceTree.package != null) ''
-          ln -s ${config.hardware.deviceTree.package} $out/dtbs
-        ''}
-
-        echo -n "$kernelParams" > $out/kernel-params
-
-        ln -s ${initrdPath} $out/initrd
-
-        ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
-
-        ln -s ${config.hardware.firmware}/lib/firmware $out/firmware
-      ''}
-
       ${if config.boot.initrd.systemd.enable then ''
         cp ${config.system.build.bootStage2} $out/prepare-root
         substituteInPlace $out/prepare-root --subst-var-by systemConfig $out
@@ -83,7 +54,6 @@ let
 
     systemd = config.systemd.package;
 
-    kernelParams = config.boot.kernelParams;
     nixosLabel = config.system.nixos.label;
 
     inherit (config.system) extraDependencies;
diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix
index 0298e28f3289..9ea611919676 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel.nix
@@ -309,6 +309,38 @@ in
 
         system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
 
+        # Not required for, e.g., containers as they don't have their own kernel or initrd.
+        # They boot directly into stage 2.
+        system.systemBuilderArgs.kernelParams = config.boot.kernelParams;
+        system.systemBuilderCommands =
+          let
+            kernelPath = "${config.boot.kernelPackages.kernel}/" +
+              "${config.system.boot.loader.kernelFile}";
+            initrdPath = "${config.system.build.initialRamdisk}/" +
+              "${config.system.boot.loader.initrdFile}";
+          in
+          ''
+            if [ ! -f ${kernelPath} ]; then
+              echo "The bootloader cannot find the proper kernel image."
+              echo "(Expecting ${kernelPath})"
+              false
+            fi
+
+            ln -s ${kernelPath} $out/kernel
+            ln -s ${config.system.modulesTree} $out/kernel-modules
+            ${optionalString (config.hardware.deviceTree.package != null) ''
+              ln -s ${config.hardware.deviceTree.package} $out/dtbs
+            ''}
+
+            echo -n "$kernelParams" > $out/kernel-params
+
+            ln -s ${initrdPath} $out/initrd
+
+            ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
+
+            ln -s ${config.hardware.firmware}/lib/firmware $out/firmware
+          '';
+
         # Implement consoleLogLevel both in early boot and using sysctl
         # (so you don't need to reboot to have changes take effect).
         boot.kernelParams =
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index 8f2f578e3070..468f701ae5bc 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -1,8 +1,32 @@
 { config, options, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib)
+    all
+    concatMap
+    concatMapStrings
+    concatStrings
+    concatStringsSep
+    escapeShellArg
+    flip
+    foldr
+    forEach
+    hasPrefix
+    mapAttrsToList
+    literalExpression
+    makeBinPath
+    mkDefault
+    mkIf
+    mkMerge
+    mkOption
+    mkRemovedOptionModule
+    mkRenamedOptionModule
+    optional
+    optionals
+    optionalString
+    replaceStrings
+    types
+  ;
 
   cfg = config.boot.loader.grub;
 
@@ -63,7 +87,9 @@ let
         extraGrubInstallArgs
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels
         default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios
-        users;
+        users
+        timeoutStyle
+      ;
       path = with pkgs; makeBinPath (
         [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ]
         ++ optional cfg.efiSupport efibootmgr
@@ -148,7 +174,7 @@ in
           (as opposed to external files) will be copied into the Nix store, and
           will be visible to all local users.
         '';
-        type = with types; attrsOf (submodule {
+        type = types.attrsOf (types.submodule {
           options = {
             hashedPasswordFile = mkOption {
               example = "/path/to/file";
@@ -425,6 +451,28 @@ in
         '';
       };
 
+      timeoutStyle = mkOption {
+        default = "menu";
+        type = types.enum [ "menu" "countdown" "hidden" ];
+        description = lib.mdDoc ''
+           - `menu` shows the menu.
+           - `countdown` uses a text-mode countdown.
+           - `hidden` hides GRUB entirely.
+
+          When using a theme, the default value (`menu`) is appropriate for the graphical countdown.
+
+          When attempting to do flicker-free boot, `hidden` should be used.
+
+          See the [GRUB documentation section about `timeout_style`](https://www.gnu.org/software/grub/manual/grub/html_node/timeout.html).
+
+          ::: {.note}
+          If this option is set to ‘countdown’ or ‘hidden’ [...] and ESC or F4 are pressed, or SHIFT is held down during that time, it will display the menu and wait for input.
+          :::
+
+          From: [Simple configuration handling page, under GRUB_TIMEOUT_STYLE](https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html).
+        '';
+      };
+
       entryOptions = mkOption {
         default = "--class nixos --unrestricted";
         type = types.nullOr types.str;
@@ -699,7 +747,7 @@ in
 
       boot.loader.grub.extraPrepareConfig =
         concatStrings (mapAttrsToList (n: v: ''
-          ${pkgs.coreutils}/bin/cp -pf "${v}" "@bootPath@/${n}"
+          ${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n}
         '') config.boot.loader.grub.extraFiles);
 
       assertions = [
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
index 27f03f2fb58c..a84e374624d1 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -75,6 +75,7 @@ my $backgroundColor = get("backgroundColor");
 my $configurationLimit = int(get("configurationLimit"));
 my $copyKernels = get("copyKernels") eq "true";
 my $timeout = int(get("timeout"));
+my $timeoutStyle = get("timeoutStyle");
 my $defaultEntry = get("default");
 my $fsIdentifier = get("fsIdentifier");
 my $grubEfi = get("grubEfi");
@@ -319,6 +320,7 @@ $conf .= "
       set default=$defaultEntryText
       set timeout=$timeout
     fi
+    set timeout_style=$timeoutStyle
 
     function savedefault {
         if [ -z \"\${boot_once}\"]; then
@@ -383,6 +385,31 @@ rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" i
 if ($theme) {
     # Copy theme
     rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n";
+
+    # Detect which modules will need to be loaded
+    my $with_png = 0;
+    my $with_jpeg = 0;
+
+    find({ wanted => sub {
+            if ($_ =~ /\.png$/i) {
+                $with_png = 1;
+            }
+            elsif ($_ =~ /\.jpe?g$/i) {
+                $with_jpeg = 1;
+            }
+    }, no_chdir => 1 }, $theme);
+
+    if ($with_png) {
+        $conf .= "
+            insmod png
+        "
+    }
+    if ($with_jpeg) {
+        $conf .= "
+            insmod jpeg
+        "
+    }
+
     $conf .= "
         # Sets theme.
         set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt
@@ -725,9 +752,8 @@ if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both"))
     if ($forceInstall eq "true") {
         push @command, "--force";
     }
-    if ($canTouchEfiVariables eq "true") {
-        push @command, "--bootloader-id=$bootloaderId";
-    } else {
+    push @command, "--bootloader-id=$bootloaderId";
+    if ($canTouchEfiVariables ne "true") {
         push @command, "--no-nvram";
         push @command, "--removable" if $efiInstallAsRemovable eq "true";
     }
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
index ee969e9bff5b..8e68431ac571 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
@@ -1,12 +1,10 @@
-# This module adds Memtest86+/Memtest86 to the GRUB boot menu.
-
+# This module adds Memtest86+ to the GRUB boot menu.
 { config, lib, pkgs, ... }:
 
 with lib;
 
 let
   memtest86 = pkgs.memtest86plus;
-  efiSupport = config.boot.loader.grub.efiSupport;
   cfg = config.boot.loader.grub.memtest86;
 in
 
@@ -19,11 +17,8 @@ in
         default = false;
         type = types.bool;
         description = lib.mdDoc ''
-          Make Memtest86+ (or MemTest86 if EFI support is enabled),
-          a memory testing program, available from the
-          GRUB boot menu. MemTest86 is an unfree program, so
-          this requires `allowUnfree` to be set to
-          `true`.
+          Make Memtest86+, a memory testing program, available from the GRUB
+          boot menu.
         '';
       };
 
@@ -63,34 +58,12 @@ in
     };
   };
 
-  config = mkMerge [
-    (mkIf (cfg.enable && efiSupport) {
-      assertions = [
-        {
-          assertion = cfg.params == [];
-          message = "Parameters are not available for MemTest86";
-        }
-      ];
-
-      boot.loader.grub.extraFiles = {
-        "memtest86.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
-      };
-
-      boot.loader.grub.extraEntries = ''
-        menuentry "Memtest86" {
-          chainloader /memtest86.efi
-        }
-      '';
-    })
-
-    (mkIf (cfg.enable && !efiSupport) {
-      boot.loader.grub.extraEntries = ''
-        menuentry "Memtest86+" {
-          linux16 @bootRoot@/memtest.bin ${toString cfg.params}
-        }
-      '';
-
-      boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
-    })
-  ];
+  config = mkIf cfg.enable {
+    boot.loader.grub.extraEntries = ''
+      menuentry "Memtest86+" {
+        linux @bootRoot@/memtest.bin ${toString cfg.params}
+      }
+    '';
+    boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
+  };
 }
diff --git a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index 8a3e89e5888b..1770f0759434 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -32,7 +32,7 @@ let
 
     inherit (config.system.nixos) distroName;
 
-    memtest86 = optionalString cfg.memtest86.enable pkgs.memtest86-efi;
+    memtest86 = optionalString cfg.memtest86.enable pkgs.memtest86plus;
 
     netbootxyz = optionalString cfg.netbootxyz.enable pkgs.netbootxyz-efi;
 
@@ -147,10 +147,8 @@ in {
         default = false;
         type = types.bool;
         description = lib.mdDoc ''
-          Make MemTest86 available from the systemd-boot menu. MemTest86 is a
-          program for testing memory.  MemTest86 is an unfree program, so
-          this requires `allowUnfree` to be set to
-          `true`.
+          Make MemTest86+ available from the systemd-boot menu. MemTest86+ is a
+          program for testing memory.
         '';
       };
 
@@ -193,8 +191,8 @@ in {
       default = {};
       example = literalExpression ''
         { "memtest86.conf" = '''
-          title MemTest86
-          efi /efi/memtest86/memtest86.efi
+          title MemTest86+
+          efi /efi/memtest86/memtest.efi
         '''; }
       '';
       description = lib.mdDoc ''
@@ -213,7 +211,7 @@ in {
       type = types.attrsOf types.path;
       default = {};
       example = literalExpression ''
-        { "efi/memtest86/memtest86.efi" = "''${pkgs.memtest86-efi}/BOOTX64.efi"; }
+        { "efi/memtest86/memtest.efi" = "''${pkgs.memtest86plus}/memtest.efi"; }
       '';
       description = lib.mdDoc ''
         A set of files to be copied to {file}`/boot`.
@@ -276,11 +274,8 @@ in {
     boot.loader.supportsInitrdSecrets = true;
 
     boot.loader.systemd-boot.extraFiles = mkMerge [
-      # TODO: This is hard-coded to use the 64-bit EFI app, but it could probably
-      # be updated to use the 32-bit EFI app on 32-bit systems.  The 32-bit EFI
-      # app filename is BOOTIA32.efi.
       (mkIf cfg.memtest86.enable {
-        "efi/memtest86/BOOTX64.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
+        "efi/memtest86/memtest.efi" = "${pkgs.memtest86plus.efi}";
       })
       (mkIf cfg.netbootxyz.enable {
         "efi/netbootxyz/netboot.xyz.efi" = "${pkgs.netbootxyz-efi}";
@@ -291,7 +286,7 @@ in {
       (mkIf cfg.memtest86.enable {
         "${cfg.memtest86.entryFilename}" = ''
           title  MemTest86
-          efi    /efi/memtest86/BOOTX64.efi
+          efi    /efi/memtest86/memtest.efi
         '';
       })
       (mkIf cfg.netbootxyz.enable {
diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix
index 20f47a76c87b..6fe460316091 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker.nix
@@ -236,8 +236,8 @@ in
       };
 
       assertions = [
-        { assertion = cfg.enableNvidia -> config.hardware.opengl.driSupport32Bit or false;
-          message = "Option enableNvidia requires 32bit support libraries";
+        { assertion = cfg.enableNvidia && pkgs.stdenv.isx86_64 -> config.hardware.opengl.driSupport32Bit or false;
+          message = "Option enableNvidia on x86_64 requires 32bit support libraries";
         }];
 
       virtualisation.docker.daemon.settings = {
diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
index 8dfe04cea542..708c577ec1ed 100644
--- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
@@ -129,6 +129,60 @@ let
       };
     };
   };
+
+  hooksModule = types.submodule {
+    options = {
+      daemon = mkOption {
+        type = types.attrsOf types.path;
+        default = { };
+        description = lib.mdDoc ''
+          Hooks that will be placed under /var/lib/libvirt/hooks/daemon.d/
+          and called for daemon start/shutdown/SIGHUP events.
+          Please see https://libvirt.org/hooks.html for documentation.
+        '';
+      };
+
+      qemu = mkOption {
+        type = types.attrsOf types.path;
+        default = { };
+        description = lib.mdDoc ''
+          Hooks that will be placed under /var/lib/libvirt/hooks/qemu.d/
+          and called for qemu domains begin/end/migrate events.
+          Please see https://libvirt.org/hooks.html for documentation.
+        '';
+      };
+
+      lxc = mkOption {
+        type = types.attrsOf types.path;
+        default = { };
+        description = lib.mdDoc ''
+          Hooks that will be placed under /var/lib/libvirt/hooks/lxc.d/
+          and called for lxc domains begin/end events.
+          Please see https://libvirt.org/hooks.html for documentation.
+        '';
+      };
+
+      libxl = mkOption {
+        type = types.attrsOf types.path;
+        default = { };
+        description = lib.mdDoc ''
+          Hooks that will be placed under /var/lib/libvirt/hooks/libxl.d/
+          and called for libxl-handled xen domains begin/end events.
+          Please see https://libvirt.org/hooks.html for documentation.
+        '';
+      };
+
+      network = mkOption {
+        type = types.attrsOf types.path;
+        default = { };
+        description = lib.mdDoc ''
+          Hooks that will be placed under /var/lib/libvirt/hooks/lxc.d/
+          and called for networks begin/end events.
+          Please see https://libvirt.org/hooks.html for documentation.
+        '';
+      };
+    };
+  };
 in
 {
 
@@ -246,6 +300,14 @@ in
         QEMU related options.
       '';
     };
+
+    hooks = mkOption {
+      type = hooksModule;
+      default = { };
+      description = lib.mdDoc ''
+        Hooks related options.
+      '';
+    };
   };
 
 
@@ -337,6 +399,15 @@ in
           ln -s --force ${ovmfpackage}/FV/AAVMF_VARS.fd /run/${dirName}/nix-ovmf/
           ln -s --force ${ovmfpackage}/FV/OVMF_VARS.fd /run/${dirName}/nix-ovmf/
         '')}
+
+        # Symlink hooks to /var/lib/libvirt
+        ${concatStringsSep "\n" (map (driver:
+          ''
+          mkdir -p /var/lib/${dirName}/hooks/${driver}.d
+          rm -rf /var/lib/${dirName}/hooks/${driver}.d/*
+          ${concatStringsSep "\n" (mapAttrsToList (name: value:
+            "ln -s --force ${value} /var/lib/${dirName}/hooks/${driver}.d/${name}") cfg.hooks.${driver})}
+        '') (attrNames cfg.hooks))}
       '';
 
       serviceConfig = {
diff --git a/nixpkgs/nixos/modules/virtualisation/lxd-agent.nix b/nixpkgs/nixos/modules/virtualisation/lxd-agent.nix
new file mode 100644
index 000000000000..5bcc86e3bcbe
--- /dev/null
+++ b/nixpkgs/nixos/modules/virtualisation/lxd-agent.nix
@@ -0,0 +1,91 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.virtualisation.lxd.agent;
+
+  # the lxd agent is provided by the lxd daemon through a virtiofs or 9p mount
+  # this is a port of the distrobuilder lxd-agent generator
+  # https://github.com/lxc/distrobuilder/blob/f77300bf7d7d5707b08eaf8a434d647d1ba81b5d/generators/lxd-agent.go#L18-L55
+  preStartScript = ''
+    PREFIX="/run/lxd_agent"
+
+    mount_virtiofs() {
+        mount -t virtiofs config "$PREFIX/.mnt" >/dev/null 2>&1
+    }
+
+    mount_9p() {
+        modprobe 9pnet_virtio >/dev/null 2>&1 || true
+        mount -t 9p config "$PREFIX/.mnt" -o access=0,trans=virtio,size=1048576 >/dev/null 2>&1
+    }
+
+    fail() {
+        umount -l "$PREFIX" >/dev/null 2>&1 || true
+        rmdir "$PREFIX" >/dev/null 2>&1 || true
+        echo "$1"
+        exit 1
+    }
+
+    # Setup the mount target.
+    umount -l "$PREFIX" >/dev/null 2>&1 || true
+    mkdir -p "$PREFIX"
+    mount -t tmpfs tmpfs "$PREFIX" -o mode=0700,size=50M
+    mkdir -p "$PREFIX/.mnt"
+
+    # Try virtiofs first.
+    mount_virtiofs || mount_9p || fail "Couldn't mount virtiofs or 9p, failing."
+
+    # Copy the data.
+    cp -Ra "$PREFIX/.mnt/"* "$PREFIX"
+
+    # Unmount the temporary mount.
+    umount "$PREFIX/.mnt"
+    rmdir "$PREFIX/.mnt"
+
+    # Fix up permissions.
+    chown -R root:root "$PREFIX"
+  '';
+in {
+  meta.maintainers = with lib.maintainers; [ adamcstephens ];
+
+  options = {
+    virtualisation.lxd.agent.enable = lib.mkEnableOption (lib.mdDoc "Enable LXD agent");
+  };
+
+  config = lib.mkIf cfg.enable {
+    # https://github.com/lxc/distrobuilder/blob/f77300bf7d7d5707b08eaf8a434d647d1ba81b5d/generators/lxd-agent.go#L108-L125
+    systemd.services.lxd-agent = {
+      enable = true;
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.kmod pkgs.util-linux ];
+
+      preStart = preStartScript;
+
+      # avoid killing nixos-rebuild switch when executed through lxc exec
+      stopIfChanged = false;
+
+      unitConfig = {
+        Description = "LXD - agent";
+        Documentation = "https://documentation.ubuntu.com/lxd/en/latest";
+        ConditionPathExists = "/dev/virtio-ports/org.linuxcontainers.lxd";
+        Before = lib.optionals config.services.cloud-init.enable [ "cloud-init.target" "cloud-init.service" "cloud-init-local.service" ];
+        DefaultDependencies = "no";
+        StartLimitInterval = "60";
+        StartLimitBurst = "10";
+      };
+
+      serviceConfig = {
+        Type = "notify";
+        WorkingDirectory = "-/run/lxd_agent";
+        ExecStart = "/run/lxd_agent/lxd-agent";
+        Restart = "on-failure";
+        RestartSec = "5s";
+      };
+    };
+
+    systemd.paths.lxd-agent = {
+      enable = true;
+      wantedBy = [ "multi-user.target" ];
+      pathConfig.PathExists = "/dev/virtio-ports/org.linuxcontainers.lxd";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/release.nix b/nixpkgs/nixos/release.nix
index 93ebe000fc00..6da6faab73be 100644
--- a/nixpkgs/nixos/release.nix
+++ b/nixpkgs/nixos/release.nix
@@ -143,7 +143,7 @@ in rec {
   manualHTML = buildFromConfig ({ ... }: { }) (config: config.system.build.manual.manualHTML);
   manual = manualHTML; # TODO(@oxij): remove eventually
   manualEpub = (buildFromConfig ({ ... }: { }) (config: config.system.build.manual.manualEpub));
-  manpages = buildFromConfig ({ ... }: { }) (config: config.system.build.manual.manpages);
+  nixos-configuration-reference-manpage = buildFromConfig ({ ... }: { }) (config: config.system.build.manual.nixos-configuration-reference-manpage);
   options = (buildFromConfig ({ ... }: { }) (config: config.system.build.manual.optionsJSON)).x86_64-linux;
 
 
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 3b4a39f5ff96..6f17bd2cdd3b 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -21,7 +21,7 @@ let
     if isAttrs val
     then
       if hasAttr "test" val then callTest val
-      else mapAttrs (n: s: discoverTests s) val
+      else mapAttrs (n: s: if n == "passthru" then s else discoverTests s) val
     else if isFunction val
       then
         # Tests based on make-test-python.nix will return the second lambda
@@ -167,6 +167,7 @@ in {
   cgit = handleTest ./cgit.nix {};
   charliecloud = handleTest ./charliecloud.nix {};
   chromium = (handleTestOn ["aarch64-linux" "x86_64-linux"] ./chromium.nix {}).stable or {};
+  chrony = handleTestOn ["aarch64-linux" "x86_64-linux"] ./chrony.nix {};
   chrony-ptp = handleTestOn ["aarch64-linux" "x86_64-linux"] ./chrony-ptp.nix {};
   cinnamon = handleTest ./cinnamon.nix {};
   cjdns = handleTest ./cjdns.nix {};
@@ -217,7 +218,7 @@ in {
   disable-installer-tools = handleTest ./disable-installer-tools.nix {};
   discourse = handleTest ./discourse.nix {};
   dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
-  dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {};
+  dnscrypt-wrapper = runTestOn ["x86_64-linux"] ./dnscrypt-wrapper;
   dnsdist = handleTest ./dnsdist.nix {};
   doas = handleTest ./doas.nix {};
   docker = handleTestOn ["aarch64-linux" "x86_64-linux"] ./docker.nix {};
@@ -252,6 +253,7 @@ in {
   envoy = handleTest ./envoy.nix {};
   ergo = handleTest ./ergo.nix {};
   ergochat = handleTest ./ergochat.nix {};
+  eris-server = handleTest ./eris-server.nix {};
   esphome = handleTest ./esphome.nix {};
   etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; };
   activation = pkgs.callPackage ../modules/system/activation/test.nix { };
@@ -365,6 +367,7 @@ in {
   iftop = handleTest ./iftop.nix {};
   incron = handleTest ./incron.nix {};
   influxdb = handleTest ./influxdb.nix {};
+  influxdb2 = handleTest ./influxdb2.nix {};
   initrd-network-openvpn = handleTest ./initrd-network-openvpn {};
   initrd-network-ssh = handleTest ./initrd-network-ssh {};
   initrd-luks-empty-passphrase = handleTest ./initrd-luks-empty-passphrase.nix {};
@@ -388,6 +391,7 @@ in {
   jibri = handleTest ./jibri.nix {};
   jirafeau = handleTest ./jirafeau.nix {};
   jitsi-meet = handleTest ./jitsi-meet.nix {};
+  jool = handleTest ./jool.nix {};
   k3s = handleTest ./k3s {};
   kafka = handleTest ./kafka.nix {};
   kanidm = handleTest ./kanidm.nix {};
@@ -461,6 +465,7 @@ in {
   matrix-conduit = handleTest ./matrix/conduit.nix {};
   matrix-synapse = handleTest ./matrix/synapse.nix {};
   mattermost = handleTest ./mattermost.nix {};
+  mediamtx = handleTest ./mediamtx.nix {};
   mediatomb = handleTest ./mediatomb.nix {};
   mediawiki = handleTest ./mediawiki.nix {};
   meilisearch = handleTest ./meilisearch.nix {};
@@ -569,6 +574,7 @@ in {
   openresty-lua = handleTest ./openresty-lua.nix {};
   opensmtpd = handleTest ./opensmtpd.nix {};
   opensmtpd-rspamd = handleTest ./opensmtpd-rspamd.nix {};
+  opensnitch = handleTest ./opensnitch.nix {};
   openssh = handleTest ./openssh.nix {};
   octoprint = handleTest ./octoprint.nix {};
   openstack-image-metadata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).metadata or {};
diff --git a/nixpkgs/nixos/tests/budgie.nix b/nixpkgs/nixos/tests/budgie.nix
index 34ee1e303de9..19d9b2bd0bed 100644
--- a/nixpkgs/nixos/tests/budgie.nix
+++ b/nixpkgs/nixos/tests/budgie.nix
@@ -52,10 +52,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           machine.wait_for_window("budgie-daemon")
           machine.wait_until_succeeds("pgrep budgie-panel")
           machine.wait_for_window("budgie-panel")
+          # We don't check xwininfo for this one.
+          # See https://github.com/NixOS/nixpkgs/pull/216737#discussion_r1155312754
+          machine.wait_until_succeeds("pgrep budgie-wm")
 
       with subtest("Open MATE terminal"):
           machine.succeed("su - ${user.name} -c 'DISPLAY=:0 mate-terminal >&2 &'")
           machine.wait_for_window("Terminal")
+
+      with subtest("Check if budgie-wm has ever coredumped"):
+          machine.fail("coredumpctl --json=short | grep budgie-wm")
           machine.sleep(20)
           machine.screenshot("screen")
     '';
diff --git a/nixpkgs/nixos/tests/caddy.nix b/nixpkgs/nixos/tests/caddy.nix
index ed88f08739e8..238091ec606f 100644
--- a/nixpkgs/nixos/tests/caddy.nix
+++ b/nixpkgs/nixos/tests/caddy.nix
@@ -22,22 +22,6 @@ import ./make-test-python.nix ({ pkgs, ... }: {
       '';
       services.caddy.enableReload = true;
 
-      specialisation.etag.configuration = {
-        services.caddy.extraConfig = lib.mkForce ''
-          http://localhost {
-            encode gzip
-
-            file_server
-            root * ${
-              pkgs.runCommand "testdir2" {} ''
-                mkdir "$out"
-                echo changed > "$out/example.html"
-              ''
-            }
-          }
-        '';
-      };
-
       specialisation.config-reload.configuration = {
         services.caddy.extraConfig = ''
           http://localhost:8080 {
@@ -55,7 +39,6 @@ import ./make-test-python.nix ({ pkgs, ... }: {
 
   testScript = { nodes, ... }:
     let
-      etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etag";
       justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/config-reload";
       multipleConfigs = "${nodes.webserver.system.build.toplevel}/specialisation/multiple-configs";
     in
@@ -65,33 +48,6 @@ import ./make-test-python.nix ({ pkgs, ... }: {
       webserver.wait_for_open_port(80)
 
 
-      def check_etag(url):
-          etag = webserver.succeed(
-              "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format(
-                  url
-              )
-          )
-          etag = etag.replace("\r\n", " ")
-          http_code = webserver.succeed(
-              "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format(
-                  etag, url
-              )
-          )
-          assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code)
-          return etag
-
-
-      with subtest("check ETag if serving Nix store paths"):
-          old_etag = check_etag(url)
-          webserver.succeed(
-              "${etagSystem}/bin/switch-to-configuration test >&2"
-          )
-          webserver.sleep(1)
-          new_etag = check_etag(url)
-          assert old_etag != new_etag, "Old ETag {} is the same as {}".format(
-              old_etag, new_etag
-          )
-
       with subtest("config is reloaded on nixos-rebuild switch"):
           webserver.succeed(
               "${justReloadSystem}/bin/switch-to-configuration test >&2"
diff --git a/nixpkgs/nixos/tests/chrony.nix b/nixpkgs/nixos/tests/chrony.nix
new file mode 100644
index 000000000000..578b1e32d50c
--- /dev/null
+++ b/nixpkgs/nixos/tests/chrony.nix
@@ -0,0 +1,31 @@
+import ./make-test-python.nix ({ lib, ... }:
+{
+  name = "chrony";
+
+  meta = {
+    maintainers = with lib.maintainers; [ fpletz ];
+  };
+
+  nodes = {
+    default = {
+      services.chrony.enable = true;
+    };
+    graphene-hardened = {
+      services.chrony.enable = true;
+      services.chrony.enableMemoryLocking = true;
+      environment.memoryAllocator.provider = "graphene-hardened";
+      # dhcpcd privsep is incompatible with graphene-hardened
+      networking.useNetworkd = true;
+    };
+  };
+
+  testScript = {nodes, ...} : let
+    graphene-hardened = nodes.graphene-hardened.system.build.toplevel;
+  in ''
+    default.start()
+    default.wait_for_unit('multi-user.target')
+    default.succeed('systemctl is-active chronyd.service')
+    default.succeed('${graphene-hardened}/bin/switch-to-configuration test')
+    default.succeed('systemctl is-active chronyd.service')
+  '';
+})
diff --git a/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix
index 1bdd064e1130..1c05376e097b 100644
--- a/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix
+++ b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix
@@ -1,4 +1,6 @@
-import ../make-test-python.nix ({ pkgs, ... }: {
+{ lib, pkgs, ... }:
+
+{
   name = "dnscrypt-wrapper";
   meta = with pkgs.lib.maintainers; {
     maintainers = [ rnhmjoj ];
@@ -50,23 +52,23 @@ import ../make-test-python.nix ({ pkgs, ... }: {
         server.wait_for_unit("dnscrypt-wrapper")
         server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.key")
         server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.crt")
+        almost_expiration = server.succeed("date --date '4days 23 hours 56min'").strip()
 
     with subtest("The client can connect to the server"):
         server.wait_for_unit("tinydns")
         client.wait_for_unit("dnscrypt-proxy2")
-        assert "1.2.3.4" in client.succeed(
+        assert "1.2.3.4" in client.wait_until_succeeds(
             "host it.works"
         ), "The IP address of 'it.works' does not match 1.2.3.4"
 
     with subtest("The server rotates the ephemeral keys"):
         # advance time by a little less than 5 days
-        server.succeed("date -s \"$(date --date '4 days 6 hours')\"")
-        client.succeed("date -s \"$(date --date '4 days 6 hours')\"")
+        server.succeed(f"date -s '{almost_expiration}'")
+        client.succeed(f"date -s '{almost_expiration}'")
         server.wait_for_file("/var/lib/dnscrypt-wrapper/oldkeys")
 
     with subtest("The client can still connect to the server"):
         server.wait_for_unit("dnscrypt-wrapper")
         client.succeed("host it.works")
   '';
-})
-
+}
diff --git a/nixpkgs/nixos/tests/eris-server.nix b/nixpkgs/nixos/tests/eris-server.nix
new file mode 100644
index 000000000000..a50db3afebf5
--- /dev/null
+++ b/nixpkgs/nixos/tests/eris-server.nix
@@ -0,0 +1,23 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "eris-server";
+  meta.maintainers = with lib.maintainers; [ ehmry ];
+
+  nodes.server = {
+    environment.systemPackages = [ pkgs.eris-go pkgs.nim.pkgs.eris ];
+    services.eris-server = {
+      enable = true;
+      decode = true;
+      listenHttp = "[::1]:80";
+      backends = [ "badger+file:///var/cache/eris.badger?get&put" ];
+      mountpoint = "/eris";
+    };
+  };
+
+  testScript = ''
+    start_all()
+    server.wait_for_unit("eris-server.service")
+    server.wait_for_open_port(5683)
+    server.wait_for_open_port(80)
+    server.succeed("eriscmd get http://[::1] $(echo 'Hail ERIS!' | eriscmd put coap+tcp://[::1]:5683)")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/fcitx5/config b/nixpkgs/nixos/tests/fcitx5/config
deleted file mode 100644
index cf4334639f1c..000000000000
--- a/nixpkgs/nixos/tests/fcitx5/config
+++ /dev/null
@@ -1,11 +0,0 @@
-[Hotkey]
-EnumerateSkipFirst=False
-
-[Hotkey/TriggerKeys]
-0=Control+space
-
-[Hotkey/EnumerateForwardKeys]
-0=Alt+Shift_L
-
-[Hotkey/EnumerateBackwardKeys]
-0=Alt+Shift_R
diff --git a/nixpkgs/nixos/tests/fcitx5/default.nix b/nixpkgs/nixos/tests/fcitx5/default.nix
index 9b000da48eaf..c113f2e2c052 100644
--- a/nixpkgs/nixos/tests/fcitx5/default.nix
+++ b/nixpkgs/nixos/tests/fcitx5/default.nix
@@ -36,6 +36,43 @@ rec {
         pkgs.fcitx5-m17n
         pkgs.fcitx5-mozc
       ];
+      fcitx5.settings = {
+        globalOptions = {
+          "Hotkey"."EnumerateSkipFirst" = "False";
+          "Hotkey/TriggerKeys"."0" = "Control+space";
+          "Hotkey/EnumerateForwardKeys"."0" = "Alt+Shift_L";
+          "Hotkey/EnumerateBackwardKeys"."0" = "Alt+Shift_R";
+        };
+        inputMethod = {
+          "GroupOrder" = {
+            "0" = "NixOS_test";
+          };
+          "Groups/0" = {
+            "Default Layout" = "us";
+            "DefaultIM" = "wbx";
+            "Name" = "NixOS_test";
+          };
+          "Groups/0/Items/0" = {
+            "Name" = "keyboard-us";
+          };
+          "Groups/0/Items/1" = {
+            "Layout" = "us";
+            "Name" = "wbx";
+          };
+          "Groups/0/Items/2" = {
+            "Layout" = "us";
+            "Name" = "hangul";
+          };
+          "Groups/0/Items/3" = {
+            "Layout" = "us";
+            "Name" = "m17n_sa_harvard-kyoto";
+          };
+          "Groups/0/Items/4" = {
+            "Layout" = "us";
+            "Name" = "mozc";
+          };
+        };
+      };
     };
   };
 
@@ -43,7 +80,6 @@ rec {
     let
       user = nodes.machine.users.users.alice;
       xauth         = "${user.home}/.Xauthority";
-      fcitx_confdir = "${user.home}/.config/fcitx5";
     in
       ''
             start_all()
@@ -56,15 +92,6 @@ rec {
             machine.succeed("su - ${user.name} -c 'kill $(pgrep fcitx5)'")
             machine.sleep(1)
 
-            machine.copy_from_host(
-                "${./profile}",
-                "${fcitx_confdir}/profile",
-            )
-            machine.copy_from_host(
-                "${./config}",
-                "${fcitx_confdir}/config",
-            )
-
             machine.succeed("su - ${user.name} -c 'alacritty >&2 &'")
             machine.succeed("su - ${user.name} -c 'fcitx5 >&2 &'")
             machine.sleep(10)
diff --git a/nixpkgs/nixos/tests/fcitx5/profile b/nixpkgs/nixos/tests/fcitx5/profile
deleted file mode 100644
index 1b48c634e0eb..000000000000
--- a/nixpkgs/nixos/tests/fcitx5/profile
+++ /dev/null
@@ -1,27 +0,0 @@
-[Groups/0]
-Name=NixOS_test
-Default Layout=us
-DefaultIM=wbx
-
-[Groups/0/Items/0]
-Name=keyboard-us
-Layout=
-
-[Groups/0/Items/1]
-Name=wbx
-Layout=us
-
-[Groups/0/Items/2]
-Name=hangul
-Layout=us
-
-[Groups/0/Items/3]
-Name=m17n_sa_harvard-kyoto
-Layout=us
-
-[Groups/0/Items/4]
-Name=mozc
-Layout=us
-
-[GroupOrder]
-0=NixOS_test
diff --git a/nixpkgs/nixos/tests/influxdb2.nix b/nixpkgs/nixos/tests/influxdb2.nix
new file mode 100644
index 000000000000..c9c54b788cc0
--- /dev/null
+++ b/nixpkgs/nixos/tests/influxdb2.nix
@@ -0,0 +1,36 @@
+import ./make-test-python.nix ({ pkgs, ...} : {
+  name = "influxdb2";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ offline ];
+  };
+
+  nodes.machine = { lib, ... }: {
+    environment.systemPackages = [ pkgs.influxdb2-cli ];
+    services.influxdb2.enable = true;
+    services.influxdb2.provision = {
+      enable = true;
+      initialSetup = {
+        organization = "default";
+        bucket = "default";
+        passwordFile = pkgs.writeText "admin-pw" "ExAmPl3PA55W0rD";
+        tokenFile = pkgs.writeText "admin-token" "verysecureadmintoken";
+      };
+    };
+  };
+
+  testScript = { nodes, ... }:
+    let
+      tokenArg = "--token verysecureadmintoken";
+    in ''
+      machine.wait_for_unit("influxdb2.service")
+
+      machine.fail("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:wrongpassword")
+      machine.succeed("curl --fail -X POST 'http://localhost:8086/api/v2/signin' -u admin:ExAmPl3PA55W0rD")
+
+      out = machine.succeed("influx org list ${tokenArg}")
+      assert "default" in out
+
+      out = machine.succeed("influx bucket list ${tokenArg} --org default")
+      assert "default" in out
+    '';
+})
diff --git a/nixpkgs/nixos/tests/jool.nix b/nixpkgs/nixos/tests/jool.nix
new file mode 100644
index 000000000000..6d5ded9b18e0
--- /dev/null
+++ b/nixpkgs/nixos/tests/jool.nix
@@ -0,0 +1,250 @@
+{ system ? builtins.currentSystem,
+  config ? {},
+  pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+
+let
+  inherit (pkgs) lib;
+
+  ipv6Only = {
+    networking.useDHCP = false;
+    networking.interfaces.eth1.ipv4.addresses = lib.mkVMOverride [ ];
+  };
+
+  ipv4Only = {
+    networking.useDHCP = false;
+    networking.interfaces.eth1.ipv6.addresses = lib.mkVMOverride [ ];
+  };
+
+  webserver = ip: msg: {
+    systemd.services.webserver = {
+      description = "Mock webserver";
+      wants = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.Restart = "always";
+      script = ''
+        while true; do
+        {
+          printf 'HTTP/1.0 200 OK\n'
+          printf 'Content-Length: ${toString (1 + builtins.stringLength msg)}\n'
+          printf '\n${msg}\n\n'
+        } | ${pkgs.libressl.nc}/bin/nc -${toString ip}nvl 80
+        done
+      '';
+    };
+    networking.firewall.allowedTCPPorts = [ 80 ];
+  };
+
+in
+
+{
+  siit = makeTest {
+    # This test simulates the setup described in [1] with two IPv6 and
+    # IPv4-only devices on different subnets communicating through a border
+    # relay running Jool in SIIT mode.
+    # [1]: https://nicmx.github.io/Jool/en/run-vanilla.html
+    name = "jool-siit";
+    meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+
+    # Border relay
+    nodes.relay = { ... }: {
+      imports = [ ../modules/profiles/minimal.nix ];
+      virtualisation.vlans = [ 1 2 ];
+
+      # Enable packet routing
+      boot.kernel.sysctl = {
+        "net.ipv6.conf.all.forwarding" = 1;
+        "net.ipv4.conf.all.forwarding" = 1;
+      };
+
+      networking.useDHCP = false;
+      networking.interfaces = lib.mkVMOverride {
+        eth1.ipv6.addresses = [ { address = "fd::198.51.100.1"; prefixLength = 120; } ];
+        eth2.ipv4.addresses = [ { address = "192.0.2.1";  prefixLength = 24; } ];
+      };
+
+      networking.jool = {
+        enable = true;
+        siit.enable = true;
+        siit.config.global.pool6 = "fd::/96";
+      };
+    };
+
+    # IPv6 only node
+    nodes.alice = { ... }: {
+      imports = [
+        ../modules/profiles/minimal.nix
+        ipv6Only
+        (webserver 6 "Hello, Bob!")
+      ];
+
+      virtualisation.vlans = [ 1 ];
+      networking.interfaces.eth1.ipv6 = {
+        addresses = [ { address = "fd::198.51.100.8"; prefixLength = 120; } ];
+        routes    = [ { address = "fd::192.0.2.0"; prefixLength = 120;
+                        via = "fd::198.51.100.1"; } ];
+      };
+    };
+
+    # IPv4 only node
+    nodes.bob = { ... }: {
+      imports = [
+        ../modules/profiles/minimal.nix
+        ipv4Only
+        (webserver 4 "Hello, Alice!")
+      ];
+
+      virtualisation.vlans = [ 2 ];
+      networking.interfaces.eth1.ipv4 = {
+        addresses = [ { address = "192.0.2.16"; prefixLength = 24; } ];
+        routes    = [ { address = "198.51.100.0"; prefixLength = 24;
+                        via = "192.0.2.1"; } ];
+      };
+    };
+
+    testScript = ''
+      start_all()
+
+      relay.wait_for_unit("jool-siit.service")
+      alice.wait_for_unit("network-addresses-eth1.service")
+      bob.wait_for_unit("network-addresses-eth1.service")
+
+      with subtest("Alice and Bob can't ping each other"):
+        relay.systemctl("stop jool-siit.service")
+        alice.fail("ping -c1 fd::192.0.2.16")
+        bob.fail("ping -c1 198.51.100.8")
+
+      with subtest("Alice and Bob can ping using the relay"):
+        relay.systemctl("start jool-siit.service")
+        alice.wait_until_succeeds("ping -c1 fd::192.0.2.16")
+        bob.wait_until_succeeds("ping -c1 198.51.100.8")
+
+      with subtest("Alice can connect to Bob's webserver"):
+        bob.wait_for_open_port(80)
+        alice.succeed("curl -vvv http://[fd::192.0.2.16] >&2")
+        alice.succeed("curl --fail -s http://[fd::192.0.2.16] | grep -q Alice")
+
+      with subtest("Bob can connect to Alices's webserver"):
+        alice.wait_for_open_port(80)
+        bob.succeed("curl --fail -s http://198.51.100.8 | grep -q Bob")
+    '';
+  };
+
+  nat64 = makeTest {
+    # This test simulates the setup described in [1] with two IPv6-only nodes
+    # (a client and a homeserver) on the LAN subnet and an IPv4 node on the WAN.
+    # The router runs Jool in stateful NAT64 mode, masquarading the LAN and
+    # forwarding ports using static BIB entries.
+    # [1]: https://nicmx.github.io/Jool/en/run-nat64.html
+    name = "jool-nat64";
+    meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+
+    # Router
+    nodes.router = { ... }: {
+      imports = [ ../modules/profiles/minimal.nix ];
+      virtualisation.vlans = [ 1 2 ];
+
+      # Enable packet routing
+      boot.kernel.sysctl = {
+        "net.ipv6.conf.all.forwarding" = 1;
+        "net.ipv4.conf.all.forwarding" = 1;
+      };
+
+      networking.useDHCP = false;
+      networking.interfaces = lib.mkVMOverride {
+        eth1.ipv6.addresses = [ { address = "2001:db8::1"; prefixLength = 96; } ];
+        eth2.ipv4.addresses = [ { address = "203.0.113.1"; prefixLength = 24; } ];
+      };
+
+      networking.jool = {
+        enable = true;
+        nat64.enable = true;
+        nat64.config = {
+          bib = [
+            { # forward HTTP 203.0.113.1 (router) → 2001:db8::9 (homeserver)
+              "protocol"     = "TCP";
+              "ipv4 address" = "203.0.113.1#80";
+              "ipv6 address" = "2001:db8::9#80";
+            }
+          ];
+          pool4 = [
+            # Ports for dynamic translation
+            { protocol =  "TCP";  prefix = "203.0.113.1/32"; "port range" = "40001-65535"; }
+            { protocol =  "UDP";  prefix = "203.0.113.1/32"; "port range" = "40001-65535"; }
+            { protocol = "ICMP";  prefix = "203.0.113.1/32"; "port range" = "40001-65535"; }
+            # Ports for static BIB entries
+            { protocol =  "TCP";  prefix = "203.0.113.1/32"; "port range" = "80"; }
+          ];
+        };
+      };
+    };
+
+    # LAN client (IPv6 only)
+    nodes.client = { ... }: {
+      imports = [ ../modules/profiles/minimal.nix ipv6Only ];
+      virtualisation.vlans = [ 1 ];
+
+      networking.interfaces.eth1.ipv6 = {
+        addresses = [ { address = "2001:db8::8"; prefixLength = 96; } ];
+        routes    = [ { address = "64:ff9b::";   prefixLength = 96;
+                        via = "2001:db8::1"; } ];
+      };
+    };
+
+    # LAN server (IPv6 only)
+    nodes.homeserver = { ... }: {
+      imports = [
+        ../modules/profiles/minimal.nix
+        ipv6Only
+        (webserver 6 "Hello from IPv6!")
+      ];
+
+      virtualisation.vlans = [ 1 ];
+      networking.interfaces.eth1.ipv6 = {
+        addresses = [ { address = "2001:db8::9"; prefixLength = 96; } ];
+        routes    = [ { address = "64:ff9b::";   prefixLength = 96;
+                        via = "2001:db8::1"; } ];
+      };
+    };
+
+    # WAN server (IPv4 only)
+    nodes.server = { ... }: {
+      imports = [
+        ../modules/profiles/minimal.nix
+        ipv4Only
+        (webserver 4 "Hello from IPv4!")
+      ];
+
+      virtualisation.vlans = [ 2 ];
+      networking.interfaces.eth1.ipv4.addresses =
+        [ { address = "203.0.113.16"; prefixLength = 24; } ];
+    };
+
+    testScript = ''
+      start_all()
+
+      for node in [client, homeserver, server]:
+        node.wait_for_unit("network-addresses-eth1.service")
+
+      with subtest("Client can ping the WAN server"):
+        router.wait_for_unit("jool-nat64.service")
+        client.succeed("ping -c1 64:ff9b::203.0.113.16")
+
+      with subtest("Client can connect to the WAN webserver"):
+        server.wait_for_open_port(80)
+        client.succeed("curl --fail -s http://[64:ff9b::203.0.113.16] | grep -q IPv4!")
+
+      with subtest("Router BIB entries are correctly populated"):
+        router.succeed("jool bib display | grep -q 'Dynamic TCP.*2001:db8::8'")
+        router.succeed("jool bib display | grep -q 'Static TCP.*2001:db8::9'")
+
+      with subtest("WAN server can reach the LAN server"):
+        homeserver.wait_for_open_port(80)
+        server.succeed("curl --fail -s http://203.0.113.1 | grep -q IPv6!")
+    '';
+
+  };
+
+}
diff --git a/nixpkgs/nixos/tests/kernel-generic.nix b/nixpkgs/nixos/tests/kernel-generic.nix
index e4a8e06df1ef..e69dd550289c 100644
--- a/nixpkgs/nixos/tests/kernel-generic.nix
+++ b/nixpkgs/nixos/tests/kernel-generic.nix
@@ -42,7 +42,9 @@ let
   };
 
 in mapAttrs (_: lP: testsForLinuxPackages lP) kernels // {
-  inherit testsForLinuxPackages;
+  passthru = {
+    inherit testsForLinuxPackages;
 
-  testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel);
+    testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel);
+  };
 }
diff --git a/nixpkgs/nixos/tests/libvirtd.nix b/nixpkgs/nixos/tests/libvirtd.nix
index b6e604075997..41d06cc9643f 100644
--- a/nixpkgs/nixos/tests/libvirtd.nix
+++ b/nixpkgs/nixos/tests/libvirtd.nix
@@ -11,6 +11,9 @@ import ./make-test-python.nix ({ pkgs, ... }: {
           memorySize = 2048;
 
           libvirtd.enable = true;
+          libvirtd.hooks.qemu.is_working = "${pkgs.writeShellScript "testHook.sh" ''
+            touch /tmp/qemu_hook_is_working
+          ''}";
         };
         boot.supportedFilesystems = [ "zfs" ];
         networking.hostId = "deadbeef"; # needed for zfs
@@ -57,5 +60,9 @@ import ./make-test-python.nix ({ pkgs, ... }: {
       virthost.shutdown()
       virthost.wait_for_unit("multi-user.target")
       virthost.wait_until_succeeds("ping -c 1 nixos")
+
+    with subtest("test if hooks are linked and run"):
+      virthost.succeed("ls /var/lib/libvirt/hooks/qemu.d/is_working")
+      virthost.succeed("ls /tmp/qemu_hook_is_working")
   '';
 })
diff --git a/nixpkgs/nixos/tests/matrix/synapse.nix b/nixpkgs/nixos/tests/matrix/synapse.nix
index 698d67c793e3..98b077469192 100644
--- a/nixpkgs/nixos/tests/matrix/synapse.nix
+++ b/nixpkgs/nixos/tests/matrix/synapse.nix
@@ -65,7 +65,7 @@ in {
 
   nodes = {
     # Since 0.33.0, matrix-synapse doesn't allow underscores in server names
-    serverpostgres = { pkgs, nodes, ... }: let
+    serverpostgres = { pkgs, nodes, config, ... }: let
       mailserverIP = nodes.mailserver.config.networking.primaryIPAddress;
     in
     {
@@ -77,6 +77,11 @@ in {
             name = "psycopg2";
             args.password = "synapse";
           };
+          redis = {
+            enabled = true;
+            host = "localhost";
+            port = config.services.redis.servers.matrix-synapse.port;
+          };
           tls_certificate_path = "${cert}";
           tls_private_key_path = "${key}";
           registration_shared_secret = registrationSharedSecret;
@@ -107,6 +112,11 @@ in {
         '';
       };
 
+      services.redis.servers.matrix-synapse = {
+        enable = true;
+        port = 6380;
+      };
+
       networking.extraHosts = ''
         ${mailserverIP} ${mailerDomain}
       '';
@@ -208,6 +218,9 @@ in {
     serverpostgres.wait_until_succeeds(
         "curl --fail -L --cacert ${ca_pem} https://localhost:8448/"
     )
+    serverpostgres.wait_until_succeeds(
+        "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("obtain-token-and-register-email")
diff --git a/nixpkgs/nixos/tests/mediamtx.nix b/nixpkgs/nixos/tests/mediamtx.nix
new file mode 100644
index 000000000000..8cacd02631d9
--- /dev/null
+++ b/nixpkgs/nixos/tests/mediamtx.nix
@@ -0,0 +1,57 @@
+import ./make-test-python.nix ({ pkgs, lib, ...} :
+
+{
+  name = "mediamtx";
+  meta.maintainers = with lib.maintainers; [ fpletz ];
+
+  nodes = {
+    machine = { config, ... }: {
+      services.mediamtx = {
+        enable = true;
+        settings = {
+          metrics = true;
+          paths.all.source = "publisher";
+        };
+      };
+
+      systemd.services.rtmp-publish = {
+        description = "Publish an RTMP stream to mediamtx";
+        after = [ "mediamtx.service" ];
+        bindsTo = [ "mediamtx.service" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          DynamicUser = true;
+          Restart = "on-failure";
+          RestartSec = "1s";
+          TimeoutStartSec = "10s";
+          ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -re -f lavfi -i smptebars=size=800x600:rate=10 -c libx264 -f flv rtmp://localhost:1935/test";
+        };
+      };
+
+      systemd.services.rtmp-receive = {
+        description = "Receive an RTMP stream from mediamtx";
+        after = [ "rtmp-publish.service" ];
+        bindsTo = [ "rtmp-publish.service" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          DynamicUser = true;
+          Restart = "on-failure";
+          RestartSec = "1s";
+          TimeoutStartSec = "10s";
+          ExecStart = "${lib.getBin pkgs.ffmpeg-headless}/bin/ffmpeg -y -re -i rtmp://localhost:1935/test -f flv /dev/null";
+        };
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    machine.wait_for_unit("mediamtx.service")
+    machine.wait_for_unit("rtmp-publish.service")
+    machine.wait_for_unit("rtmp-receive.service")
+    machine.wait_for_open_port(9998)
+    machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"publish\".*1$'")
+    machine.succeed("curl http://localhost:9998/metrics | grep '^rtmp_conns.*state=\"read\".*1$'")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/netdata.nix b/nixpkgs/nixos/tests/netdata.nix
index aea67c29d0d4..c5f7294f79ab 100644
--- a/nixpkgs/nixos/tests/netdata.nix
+++ b/nixpkgs/nixos/tests/netdata.nix
@@ -10,7 +10,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     netdata =
       { pkgs, ... }:
         {
-          environment.systemPackages = with pkgs; [ curl jq ];
+          environment.systemPackages = with pkgs; [ curl jq netdata ];
           services.netdata.enable = true;
         };
     };
@@ -34,5 +34,8 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     filter = '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0'
     cmd = f"curl -s {url} | jq -e '{filter}'"
     netdata.wait_until_succeeds(cmd)
+
+    # check if the control socket is available
+    netdata.succeed("sudo netdatacli ping")
   '';
 })
diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix
index db5cee9f6584..b7af6d6d7364 100644
--- a/nixpkgs/nixos/tests/nextcloud/basic.nix
+++ b/nixpkgs/nixos/tests/nextcloud/basic.nix
@@ -90,8 +90,8 @@ in {
       test -e graph
       grep "$what" graph >$out || true
     '';
-    nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.config.system.build.vm;
-    nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.config.system.build.vm;
+    nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.system.build.vm;
+    nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.system.build.vm;
   in ''
     assert open("${nextcloudUsesImagick}").read() != ""
     assert open("${nextcloudWithoutDoesntUseIt}").read() == ""
diff --git a/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix b/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix
index 92beb869eb03..d6ea39c6155a 100644
--- a/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix
+++ b/nixpkgs/nixos/tests/nextcloud/openssl-sse.nix
@@ -49,8 +49,8 @@ in {
       #!${pkgs.runtimeShell}
       echo 'bye' | ${withRcloneEnv3} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file2
     '';
-    openssl1-node = nodes.nextcloudwithopenssl1.config.system.build.toplevel;
-    openssl3-node = nodes.nextcloudwithopenssl3.config.system.build.toplevel;
+    openssl1-node = nodes.nextcloudwithopenssl1.system.build.toplevel;
+    openssl3-node = nodes.nextcloudwithopenssl3.system.build.toplevel;
   in ''
     nextcloudwithopenssl1.start()
     nextcloudwithopenssl1.wait_for_unit("multi-user.target")
diff --git a/nixpkgs/nixos/tests/nixops/default.nix b/nixpkgs/nixos/tests/nixops/default.nix
index bd00e6143639..b8f747b2a19f 100644
--- a/nixpkgs/nixos/tests/nixops/default.nix
+++ b/nixpkgs/nixos/tests/nixops/default.nix
@@ -14,11 +14,12 @@ let
     # inherit testsForPackage;
   };
 
-  testsForPackage = lib.makeOverridable (args: lib.recurseIntoAttrs {
+  testsForPackage = args: lib.recurseIntoAttrs {
     legacyNetwork = testLegacyNetwork args;
-  });
+    passthru.override = args': testsForPackage (args // args');
+  };
 
-  testLegacyNetwork = { nixopsPkg }: pkgs.nixosTest ({
+  testLegacyNetwork = { nixopsPkg, ... }: pkgs.nixosTest ({
     name = "nixops-legacy-network";
     nodes = {
       deployer = { config, lib, nodes, pkgs, ... }: {
@@ -52,7 +53,7 @@ let
           chmod 0400 ~/.ssh/id_ed25519
         '';
         serverNetworkJSON = pkgs.writeText "server-network.json"
-          (builtins.toJSON nodes.server.config.system.build.networkConfig);
+          (builtins.toJSON nodes.server.system.build.networkConfig);
       in
       ''
         import shlex
diff --git a/nixpkgs/nixos/tests/opensnitch.nix b/nixpkgs/nixos/tests/opensnitch.nix
new file mode 100644
index 000000000000..d84e4e0a935b
--- /dev/null
+++ b/nixpkgs/nixos/tests/opensnitch.nix
@@ -0,0 +1,62 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "opensnitch";
+
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ onny ];
+  };
+
+  nodes = {
+    server =
+      { ... }: {
+        networking.firewall.allowedTCPPorts = [ 80 ];
+        services.caddy = {
+          enable = true;
+          virtualHosts."localhost".extraConfig = ''
+            respond "Hello, world!"
+          '';
+        };
+      };
+
+    clientBlocked =
+      { ... }: {
+        services.opensnitch = {
+          enable = true;
+          settings.DefaultAction = "deny";
+        };
+      };
+
+    clientAllowed =
+      { ... }: {
+        services.opensnitch = {
+          enable = true;
+          settings.DefaultAction = "deny";
+          rules = {
+            opensnitch = {
+              name = "curl";
+              enabled = true;
+              action = "allow";
+              duration = "always";
+              operator = {
+                type ="simple";
+                sensitive = false;
+                operand = "process.path";
+                data = "${pkgs.curl}/bin/curl";
+              };
+            };
+          };
+        };
+      };
+  };
+
+  testScript = ''
+    start_all()
+    server.wait_for_unit("caddy.service")
+    server.wait_for_open_port(80)
+
+    clientBlocked.wait_for_unit("opensnitchd.service")
+    clientBlocked.fail("curl http://server")
+
+    clientAllowed.wait_for_unit("opensnitchd.service")
+    clientAllowed.succeed("curl http://server")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/pantheon.nix b/nixpkgs/nixos/tests/pantheon.nix
index 653fcc6edad1..dee6964644c5 100644
--- a/nixpkgs/nixos/tests/pantheon.nix
+++ b/nixpkgs/nixos/tests/pantheon.nix
@@ -60,6 +60,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
     with subtest("Open elementary terminal"):
         machine.execute("su - ${user.name} -c 'DISPLAY=:0 io.elementary.terminal >&2 &'")
         machine.wait_for_window("io.elementary.terminal")
+
+    with subtest("Check if gala has ever coredumped"):
+        machine.fail("coredumpctl --json=short | grep gala")
         machine.sleep(20)
         machine.screenshot("screen")
   '';
diff --git a/nixpkgs/nixos/tests/prometheus-exporters.nix b/nixpkgs/nixos/tests/prometheus-exporters.nix
index 23740dd98e3d..d86f8ac634e8 100644
--- a/nixpkgs/nixos/tests/prometheus-exporters.nix
+++ b/nixpkgs/nixos/tests/prometheus-exporters.nix
@@ -307,6 +307,23 @@ let
       '';
     };
 
+    idrac = {
+      exporterConfig = {
+        enable = true;
+        port = 9348;
+        configuration = {
+          hosts = {
+            default = { username = "username"; password = "password"; };
+          };
+        };
+      };
+      exporterTest = ''
+        wait_for_unit("prometheus-idrac-exporter.service")
+        wait_for_open_port(9348)
+        wait_until_succeeds("curl localhost:9348")
+      '';
+    };
+
     influxdb = {
       exporterConfig = {
         enable = true;
@@ -1183,7 +1200,7 @@ let
       };
       exporterTest = ''
         wait_until_succeeds(
-            'journalctl -eu prometheus-smartctl-exporter.service -o cat | grep "Device unavailable"'
+            'journalctl -eu prometheus-smartctl-exporter.service -o cat | grep "Unable to detect device type"'
         )
       '';
     };
diff --git a/nixpkgs/nixos/tests/switch-test.nix b/nixpkgs/nixos/tests/switch-test.nix
index f44dede7fef4..53595ae7d3e2 100644
--- a/nixpkgs/nixos/tests/switch-test.nix
+++ b/nixpkgs/nixos/tests/switch-test.nix
@@ -1,6 +1,6 @@
 # Test configuration switching.
 
-import ./make-test-python.nix ({ pkgs, ...} : let
+import ./make-test-python.nix ({ lib, pkgs, ...} : let
 
   # Simple service that can either be socket-activated or that will
   # listen on port 1234 if not socket-activated.
@@ -279,6 +279,28 @@ in {
           systemd.services.test-service.unitConfig.RefuseManualStart = true;
         };
 
+        unitWithTemplate.configuration = {
+          systemd.services."instantiated@".serviceConfig = {
+            Type = "oneshot";
+            RemainAfterExit = true;
+            ExecStart = "${pkgs.coreutils}/bin/true";
+            ExecReload = "${pkgs.coreutils}/bin/true";
+          };
+          systemd.services."instantiated@one" = {
+            wantedBy = [ "multi-user.target" ];
+            overrideStrategy = "asDropin";
+          };
+          systemd.services."instantiated@two" = {
+            wantedBy = [ "multi-user.target" ];
+            overrideStrategy = "asDropin";
+          };
+        };
+
+        unitWithTemplateModified.configuration = {
+          imports = [ unitWithTemplate.configuration ];
+          systemd.services."instantiated@".serviceConfig.X-Test = "test";
+        };
+
         restart-and-reload-by-activation-script.configuration = {
           systemd.services = rec {
             simple-service = {
@@ -290,29 +312,50 @@ in {
                 ExecReload = "${pkgs.coreutils}/bin/true";
               };
             };
+            "templated-simple-service@" = simple-service;
+            "templated-simple-service@instance".overrideStrategy = "asDropin";
 
             simple-restart-service = simple-service // {
               stopIfChanged = false;
             };
+            "templated-simple-restart-service@" = simple-restart-service;
+            "templated-simple-restart-service@instance".overrideStrategy = "asDropin";
 
             simple-reload-service = simple-service // {
               reloadIfChanged = true;
             };
+            "templated-simple-reload-service@" = simple-reload-service;
+            "templated-simple-reload-service@instance".overrideStrategy = "asDropin";
 
             no-restart-service = simple-service // {
               restartIfChanged = false;
             };
+            "templated-no-restart-service@" = no-restart-service;
+            "templated-no-restart-service@instance".overrideStrategy = "asDropin";
 
             reload-triggers = simple-service // {
               wantedBy = [ "multi-user.target" ];
             };
+            "templated-reload-triggers@" = simple-service;
+            "templated-reload-triggers@instance" = {
+              overrideStrategy = "asDropin";
+              wantedBy = [ "multi-user.target" ];
+            };
 
             reload-triggers-and-restart-by-as = simple-service;
+            "templated-reload-triggers-and-restart-by-as@" = reload-triggers-and-restart-by-as;
+            "templated-reload-triggers-and-restart-by-as@instance".overrideStrategy = "asDropin";
 
             reload-triggers-and-restart = simple-service // {
               stopIfChanged = false; # easier to check for this
               wantedBy = [ "multi-user.target" ];
             };
+            "templated-reload-triggers-and-restart@" = simple-service;
+            "templated-reload-triggers-and-restart@instance" = {
+              overrideStrategy = "asDropin";
+              stopIfChanged = false; # easier to check for this
+              wantedBy = [ "multi-user.target" ];
+            };
           };
 
           system.activationScripts.restart-and-reload-test = {
@@ -332,12 +375,20 @@ in {
               simple-reload-service.service
               no-restart-service.service
               reload-triggers-and-restart-by-as.service
+              templated-simple-service@instance.service
+              templated-simple-restart-service@instance.service
+              templated-simple-reload-service@instance.service
+              templated-no-restart-service@instance.service
+              templated-reload-triggers-and-restart-by-as@instance.service
               EOF
 
               cat <<EOF >> "$g"
               reload-triggers.service
               reload-triggers-and-restart-by-as.service
               reload-triggers-and-restart.service
+              templated-reload-triggers@instance.service
+              templated-reload-triggers-and-restart-by-as@instance.service
+              templated-reload-triggers-and-restart@instance.service
               EOF
             '';
           };
@@ -346,6 +397,10 @@ in {
         restart-and-reload-by-activation-script-modified.configuration = {
           imports = [ restart-and-reload-by-activation-script.configuration ];
           systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test";
+          systemd.services."templated-reload-triggers-and-restart@instance" = {
+            overrideStrategy = "asDropin";
+            serviceConfig.X-Modified = "test";
+          };
         };
 
         simple-socket.configuration = {
@@ -507,6 +562,10 @@ in {
       set -o pipefail
       exec env -i "$@" | tee /dev/stderr
     '';
+
+    # Returns a comma separated representation of the given list in sorted
+    # order, that matches the output format of switch-to-configuration.pl
+    sortedUnits = xs: lib.concatStringsSep ", " (builtins.sort builtins.lessThan xs);
   in /* python */ ''
     def switch_to_specialisation(system, name, action="test", fail=False):
         if name == "":
@@ -733,6 +792,16 @@ in {
         assert_contains(out, "\nstarting the following units: required-service.service\n")
         assert_lacks(out, "the following new units were started:")
 
+        # Ensure templated units are restarted when the base unit changes
+        switch_to_specialisation("${machine}", "unitWithTemplate")
+        out = switch_to_specialisation("${machine}", "unitWithTemplateModified")
+        assert_contains(out, "stopping the following units: instantiated@one.service, instantiated@two.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_contains(out, "\nstarting the following units: instantiated@one.service, instantiated@two.service\n")
+        assert_lacks(out, "the following new units were started:")
+
     with subtest("failing units"):
         # Let the simple service fail
         switch_to_specialisation("${machine}", "simpleServiceModified")
@@ -896,15 +965,62 @@ in {
         assert_lacks(out, "NOT restarting the following changed units:")
         assert_lacks(out, "reloading the following units:")
         assert_lacks(out, "restarting the following units:")
-        assert_contains(out, "\nstarting the following units: no-restart-service.service, reload-triggers-and-restart-by-as.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
-        assert_contains(out, "the following new units were started: no-restart-service.service, reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
+        assert_contains(out, "\nstarting the following units: ${sortedUnits [
+          "no-restart-service.service"
+          "reload-triggers-and-restart-by-as.service"
+          "simple-reload-service.service"
+          "simple-restart-service.service"
+          "simple-service.service"
+          "templated-no-restart-service@instance.service"
+          "templated-reload-triggers-and-restart-by-as@instance.service"
+          "templated-simple-reload-service@instance.service"
+          "templated-simple-restart-service@instance.service"
+          "templated-simple-service@instance.service"
+        ]}\n")
+        assert_contains(out, "the following new units were started: ${sortedUnits [
+          "no-restart-service.service"
+          "reload-triggers-and-restart-by-as.service"
+          "reload-triggers-and-restart.service"
+          "reload-triggers.service"
+          "simple-reload-service.service"
+          "simple-restart-service.service"
+          "simple-service.service"
+          "system-templated\\\\x2dno\\\\x2drestart\\\\x2dservice.slice"
+          "system-templated\\\\x2dreload\\\\x2dtriggers.slice"
+          "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart.slice"
+          "system-templated\\\\x2dreload\\\\x2dtriggers\\\\x2dand\\\\x2drestart\\\\x2dby\\\\x2das.slice"
+          "system-templated\\\\x2dsimple\\\\x2dreload\\\\x2dservice.slice"
+          "system-templated\\\\x2dsimple\\\\x2drestart\\\\x2dservice.slice"
+          "system-templated\\\\x2dsimple\\\\x2dservice.slice"
+          "templated-no-restart-service@instance.service"
+          "templated-reload-triggers-and-restart-by-as@instance.service"
+          "templated-reload-triggers-and-restart@instance.service"
+          "templated-reload-triggers@instance.service"
+          "templated-simple-reload-service@instance.service"
+          "templated-simple-restart-service@instance.service"
+          "templated-simple-service@instance.service"
+        ]}\n")
         # Switch to the same system where the example services get restarted
         # and reloaded by the activation script
         out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
         assert_lacks(out, "stopping the following units:")
         assert_lacks(out, "NOT restarting the following changed units:")
-        assert_contains(out, "reloading the following units: reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service\n")
-        assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, simple-restart-service.service, simple-service.service\n")
+        assert_contains(out, "reloading the following units: ${sortedUnits [
+          "reload-triggers-and-restart.service"
+          "reload-triggers.service"
+          "simple-reload-service.service"
+          "templated-reload-triggers-and-restart@instance.service"
+          "templated-reload-triggers@instance.service"
+          "templated-simple-reload-service@instance.service"
+        ]}\n")
+        assert_contains(out, "restarting the following units: ${sortedUnits [
+          "reload-triggers-and-restart-by-as.service"
+          "simple-restart-service.service"
+          "simple-service.service"
+          "templated-reload-triggers-and-restart-by-as@instance.service"
+          "templated-simple-restart-service@instance.service"
+          "templated-simple-service@instance.service"
+        ]}\n")
         assert_lacks(out, "\nstarting the following units:")
         assert_lacks(out, "the following new units were started:")
         # Switch to the same system and see if the service gets restarted when it's modified
@@ -912,16 +1028,44 @@ in {
         out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
         assert_lacks(out, "stopping the following units:")
         assert_lacks(out, "NOT restarting the following changed units:")
-        assert_contains(out, "reloading the following units: reload-triggers.service, simple-reload-service.service\n")
-        assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
+        assert_contains(out, "reloading the following units: ${sortedUnits [
+          "reload-triggers.service"
+          "simple-reload-service.service"
+          "templated-reload-triggers@instance.service"
+          "templated-simple-reload-service@instance.service"
+        ]}\n")
+        assert_contains(out, "restarting the following units: ${sortedUnits [
+          "reload-triggers-and-restart-by-as.service"
+          "reload-triggers-and-restart.service"
+          "simple-restart-service.service"
+          "simple-service.service"
+          "templated-reload-triggers-and-restart-by-as@instance.service"
+          "templated-reload-triggers-and-restart@instance.service"
+          "templated-simple-restart-service@instance.service"
+          "templated-simple-service@instance.service"
+        ]}\n")
         assert_lacks(out, "\nstarting the following units:")
         assert_lacks(out, "the following new units were started:")
         # The same, but in dry mode
         out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
         assert_lacks(out, "would stop the following units:")
         assert_lacks(out, "would NOT stop the following changed units:")
-        assert_contains(out, "would reload the following units: reload-triggers.service, simple-reload-service.service\n")
-        assert_contains(out, "would restart the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
+        assert_contains(out, "would reload the following units: ${sortedUnits [
+          "reload-triggers.service"
+          "simple-reload-service.service"
+          "templated-reload-triggers@instance.service"
+          "templated-simple-reload-service@instance.service"
+        ]}\n")
+        assert_contains(out, "would restart the following units: ${sortedUnits [
+          "reload-triggers-and-restart-by-as.service"
+          "reload-triggers-and-restart.service"
+          "simple-restart-service.service"
+          "simple-service.service"
+          "templated-reload-triggers-and-restart-by-as@instance.service"
+          "templated-reload-triggers-and-restart@instance.service"
+          "templated-simple-restart-service@instance.service"
+          "templated-simple-service@instance.service"
+        ]}\n")
         assert_lacks(out, "\nwould start the following units:")
 
     with subtest("socket-activated services"):
diff --git a/nixpkgs/nixos/tests/systemd-boot.nix b/nixpkgs/nixos/tests/systemd-boot.nix
index 84a4da5aa6ec..c1f8637989e3 100644
--- a/nixpkgs/nixos/tests/systemd-boot.nix
+++ b/nixpkgs/nixos/tests/systemd-boot.nix
@@ -118,14 +118,11 @@ in
     nodes.machine = { pkgs, lib, ... }: {
       imports = [ common ];
       boot.loader.systemd-boot.memtest86.enable = true;
-      nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
-        "memtest86-efi"
-      ];
     };
 
     testScript = ''
       machine.succeed("test -e /boot/loader/entries/memtest86.conf")
-      machine.succeed("test -e /boot/efi/memtest86/BOOTX64.efi")
+      machine.succeed("test -e /boot/efi/memtest86/memtest.efi")
     '';
   };
 
@@ -152,15 +149,12 @@ in
       imports = [ common ];
       boot.loader.systemd-boot.memtest86.enable = true;
       boot.loader.systemd-boot.memtest86.entryFilename = "apple.conf";
-      nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
-        "memtest86-efi"
-      ];
     };
 
     testScript = ''
       machine.fail("test -e /boot/loader/entries/memtest86.conf")
       machine.succeed("test -e /boot/loader/entries/apple.conf")
-      machine.succeed("test -e /boot/efi/memtest86/BOOTX64.efi")
+      machine.succeed("test -e /boot/efi/memtest86/memtest.efi")
     '';
   };
 
diff --git a/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix b/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix
index 2fd3983e13ec..715477191bfb 100644
--- a/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix
+++ b/nixpkgs/nixos/tests/web-apps/mastodon/remote-postgresql.nix
@@ -13,7 +13,7 @@ let
 in
 {
   name = "mastodon-remote-postgresql";
-  meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin turion ];
+  meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin ];
 
   nodes = {
     database = {
diff --git a/nixpkgs/nixos/tests/web-servers/agate.nix b/nixpkgs/nixos/tests/web-servers/agate.nix
index e8d789a9ca44..0de27b6f7d8d 100644
--- a/nixpkgs/nixos/tests/web-servers/agate.nix
+++ b/nixpkgs/nixos/tests/web-servers/agate.nix
@@ -20,7 +20,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/wrappers.nix b/nixpkgs/nixos/tests/wrappers.nix
index 08c1ad0b6b99..391e9b42b45b 100644
--- a/nixpkgs/nixos/tests/wrappers.nix
+++ b/nixpkgs/nixos/tests/wrappers.nix
@@ -55,6 +55,10 @@ in
         out = machine.succeed(cmd_as_regular(cmd)).strip()
         assert out == expected, "Expected {0} to output {1}, but got {2}".format(cmd, expected, out)
 
+      def test_as_regular_in_userns_mapped_as_root(cmd, expected):
+        out = machine.succeed(f"su -l regular -c '${pkgs.util-linux}/bin/unshare -rm {cmd}'").strip()
+        assert out == expected, "Expected {0} to output {1}, but got {2}".format(cmd, expected, out)
+
       test_as_regular('${busybox pkgs}/bin/busybox id -u', '${toString userUid}')
       test_as_regular('${busybox pkgs}/bin/busybox id -ru', '${toString userUid}')
       test_as_regular('${busybox pkgs}/bin/busybox id -g', '${toString usersGid}')
@@ -70,10 +74,27 @@ in
       test_as_regular('/run/wrappers/bin/sgid_root_busybox id -g', '0')
       test_as_regular('/run/wrappers/bin/sgid_root_busybox id -rg', '${toString usersGid}')
 
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -u', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -ru', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -g', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/suid_root_busybox id -rg', '0')
+
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -u', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -ru', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -g', '0')
+      test_as_regular_in_userns_mapped_as_root('/run/wrappers/bin/sgid_root_busybox id -rg', '0')
+
       # We are only testing the permitted set, because it's easiest to look at with capsh.
       machine.fail(cmd_as_regular('${pkgs.libcap}/bin/capsh --has-p=CAP_CHOWN'))
       machine.fail(cmd_as_regular('${pkgs.libcap}/bin/capsh --has-p=CAP_SYS_ADMIN'))
       machine.succeed(cmd_as_regular('/run/wrappers/bin/capsh_with_chown --has-p=CAP_CHOWN'))
       machine.fail(cmd_as_regular('/run/wrappers/bin/capsh_with_chown --has-p=CAP_SYS_ADMIN'))
+
+      # test a few "attacks" against which the wrapper protects itself
+      machine.succeed("cp /run/wrappers/bin/suid_root_busybox{,.real} /tmp/")
+      machine.fail(cmd_as_regular("/tmp/suid_root_busybox id -u"))
+
+      machine.succeed("chmod u+s,a+w /run/wrappers/bin/suid_root_busybox")
+      machine.fail(cmd_as_regular("/run/wrappers/bin/suid_root_busybox id -u"))
     '';
 })