about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-09-12 08:14:37 +0000
committerAlyssa Ross <hi@alyssa.is>2023-09-12 08:14:37 +0000
commit7d648ac22d941d0c7efdd987315ae0ddf9932ba0 (patch)
tree51a3e8126722c5a52a9a1e7e40b4eeaf4610db0b /nixpkgs/nixos
parentaa4353b499e6950b7333578f936455a628145c31 (diff)
parentdb9208ab987cdeeedf78ad9b4cf3c55f5ebd269b (diff)
downloadnixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar.gz
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar.bz2
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar.lz
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar.xz
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.tar.zst
nixlib-7d648ac22d941d0c7efdd987315ae0ddf9932ba0.zip
Merge branch 'nixos-unstable' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md22
-rw-r--r--nixpkgs/nixos/lib/testing/driver.nix7
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix20
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image.nix (renamed from nixpkgs/nixos/maintainers/scripts/lxd/lxd-image.nix)6
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-image-inner.nix95
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image-inner.nix20
-rw-r--r--nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix27
-rw-r--r--nixpkgs/nixos/modules/config/update-users-groups.pl15
-rw-r--r--nixpkgs/nixos/modules/config/users-groups.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/infiniband.nix58
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/uim.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix1
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix129
-rw-r--r--nixpkgs/nixos/modules/module-list.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/ecryptfs.nix31
-rw-r--r--nixpkgs/nixos/modules/programs/streamdeck-ui.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/yazi.nix49
-rw-r--r--nixpkgs/nixos/modules/security/sudo.nix4
-rw-r--r--nixpkgs/nixos/modules/services/backup/duplicati.nix7
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix8
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/github-runner/service.nix5
-rw-r--r--nixpkgs/nixos/modules/services/databases/surrealdb.nix29
-rw-r--r--nixpkgs/nixos/modules/services/hardware/auto-cpufreq.nix7
-rw-r--r--nixpkgs/nixos/modules/services/hardware/openrgb.nix9
-rw-r--r--nixpkgs/nixos/modules/services/mail/stalwart-mail.nix106
-rw-r--r--nixpkgs/nixos/modules/services/matrix/mautrix-telegram.nix1
-rw-r--r--nixpkgs/nixos/modules/services/matrix/mautrix-whatsapp.nix99
-rw-r--r--nixpkgs/nixos/modules/services/misc/atuin.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitlab.nix7
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/mimir.nix14
-rw-r--r--nixpkgs/nixos/modules/services/networking/dae.nix170
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix6
-rw-r--r--nixpkgs/nixos/modules/services/networking/jool.nix313
-rw-r--r--nixpkgs/nixos/modules/services/networking/nftables.nix22
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.nix16
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mobilizon.nix442
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/nginx/default.nix12
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix3
-rwxr-xr-xnixpkgs/nixos/modules/system/boot/stage-2-init.sh5
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd/initrd.nix16
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd/user.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/anbox.nix59
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxc-container.nix130
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxc-image-metadata.nix104
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxc-instance-common.nix30
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix46
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxd.nix129
-rw-r--r--nixpkgs/nixos/release.nix51
-rw-r--r--nixpkgs/nixos/tests/akkoma.nix5
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix8
-rw-r--r--nixpkgs/nixos/tests/anbox.nix40
-rw-r--r--nixpkgs/nixos/tests/custom-ca.nix4
-rw-r--r--nixpkgs/nixos/tests/dae.nix29
-rw-r--r--nixpkgs/nixos/tests/jool.nix106
-rw-r--r--nixpkgs/nixos/tests/lxd/container.nix13
-rw-r--r--nixpkgs/nixos/tests/lxd/default.nix3
-rw-r--r--nixpkgs/nixos/tests/lxd/preseed.nix71
-rw-r--r--nixpkgs/nixos/tests/lxd/virtual-machine.nix64
-rw-r--r--nixpkgs/nixos/tests/mobilizon.nix44
-rw-r--r--nixpkgs/nixos/tests/stalwart-mail.nix117
-rw-r--r--nixpkgs/nixos/tests/user-activation-scripts.nix3
61 files changed, 2193 insertions, 660 deletions
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 c4ed81e0b5b6..85c3ee7a1aa0 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -6,6 +6,8 @@
 
 - Support for WiFi6 (IEEE 802.11ax) and WPA3-SAE-PK was enabled in the `hostapd` package, along with a significant rework of the hostapd module.
 
+- LXD now supports virtual machine instances to complement the existing container support
+
 ## New Services {#sec-release-23.11-new-services}
 
 - [MCHPRS](https://github.com/MCHPR/MCHPRS), a multithreaded Minecraft server built for redstone. Available as [services.mchprs](#opt-services.mchprs.enable).
@@ -28,13 +30,17 @@
 
 * [NS-USBLoader](https://github.com/developersu/ns-usbloader/), an all-in-one tool for managing Nintendo Switch homebrew. Available as [programs.ns-usbloader](#opt-programs.ns-usbloader.enable).
 
+- [Mobilizon](https://joinmobilizon.org/), a Fediverse platform for publishing events.
+
 - [Anuko Time Tracker](https://github.com/anuko/timetracker), a simple, easy to use, open source time tracking system. Available as [services.anuko-time-tracker](#opt-services.anuko-time-tracker.enable).
 
 - [Prometheus MySQL exporter](https://github.com/prometheus/mysqld_exporter), a MySQL server exporter for Prometheus. Available as [services.prometheus.exporters.mysqld](#opt-services.prometheus.exporters.mysqld.enable).
 
 - [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).
+- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).
+
+- [Jool](https://nicmx.github.io/Jool/en/index.html), a kernelspace NAT64 and SIIT implementation, providing translation between IPv4 and IPv6. Available as [networking.jool.enable](#opt-networking.jool.enable).
 
 - [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.
 
@@ -50,6 +56,8 @@
 
 - [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).
 
+- hardware/infiniband.nix adds infiniband subnet manager support using an [opensm](https://github.com/linux-rdma/opensm) systemd-template service, instantiated on card guids. The module also adds kernel modules and cli tooling to help administrators debug and measure performance. Available as [hardware.infiniband.enable](#opt-hardware.infiniband.enable).
+
 - [Honk](https://humungus.tedunangst.com/r/honk), a complete ActivityPub server with minimal setup and support costs.
   Available as [services.honk](#opt-services.honk.enable).
 
@@ -75,12 +83,16 @@
 
 - `pass` now does not contain `password-store.el`.  Users should get `password-store.el` from Emacs lisp package set `emacs.pkgs.password-store`.
 
+- `mu` now does not install `mu4e` files by default.  Users should get `mu4e` from Emacs lisp package set `emacs.pkgs.mu4e`.
+
 - `mariadb` now defaults to `mariadb_1011` instead of `mariadb_106`, meaning the default version was upgraded from 10.6.x to 10.11.x. See the [upgrade notes](https://mariadb.com/kb/en/upgrading-from-mariadb-10-6-to-mariadb-10-11/) for potential issues.
 
 - `getent` has been moved from `glibc`'s `bin` output to its own dedicated output, reducing closure size for many dependents. Dependents using the `getent` alias should not be affected; others should move from using `glibc.bin` or `getBin glibc` to `getent` (which also improves compatibility with non-glibc platforms).
 
 - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`.
 
+- JACK tools (`jack_*` except `jack_control`) have moved from the `jack2` package to `jack-example-tools`
+
 - 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.
@@ -90,6 +102,8 @@
 
 - `etcd` has been updated to 3.5, you will want to read the [3.3 to 3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [3.4 to 3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) upgrade guides
 
+- `gitlab` installations created or updated between versions \[15.11.0, 15.11.2] have an incorrect database schema. This will become a problem when upgrading to `gitlab` >=16.2.0. A workaround for affected users can be found in the [GitLab docs](https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html#undefined-column-error-upgrading-to-162-or-later).
+
 - `consul` has been updated to `1.16.0`. See the [release note](https://github.com/hashicorp/consul/releases/tag/v1.16.0) for more details. Once a new Consul version has started and upgraded its data directory, it generally cannot be downgraded to the previous version.
 
 - `himalaya` has been updated to `0.8.0`, which drops the native TLS support (in favor of Rustls) and add OAuth 2.0 support. See the [release note](https://github.com/soywod/himalaya/releases/tag/v0.8.0) for more details.
@@ -171,6 +185,8 @@
 
 - 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).
 
+- `kratos` has been updated from 0.10.1 to the first stable version 1.0.0, please read the [0.10.1 to 0.11.0](https://github.com/ory/kratos/releases/tag/v0.11.0), [0.11.0 to 0.11.1](https://github.com/ory/kratos/releases/tag/v0.11.1), [0.11.1 to 0.13.0](https://github.com/ory/kratos/releases/tag/v0.13.0) and [0.13.0 to 1.0.0](https://github.com/ory/kratos/releases/tag/v1.0.0) upgrade guides. The most notable breaking change is the introduction of one-time passwords (`code`) and update of the default recovery strategy from `link` to `code`.
+
 ## 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.
@@ -221,6 +237,8 @@ The module update takes care of the new config syntax and the data itself (user
 
 - `services.prometheus.exporters` has a new [exporter](https://github.com/hipages/php-fpm_exporter) to monitor PHP-FPM processes, see [#240394](https://github.com/NixOS/nixpkgs/pull/240394) for more details.
 
+- `services.github-runner` / `services.github-runners.<name>` gained the option `nodeRuntimes`. The option defaults to `[ "node20" ]`, i.e., the service supports Node.js 20 GitHub Actions only. The list of Node.js versions accepted by `nodeRuntimes` tracks the versions the upstream GitHub Actions runner supports. See [#249103](https://github.com/NixOS/nixpkgs/pull/249103) for details.
+
 - `programs.gnupg.agent.pinentryFlavor` is now set in `/etc/gnupg/gpg-agent.conf`, and will no longer take precedence over a `pinentry-program` set in `~/.gnupg/gpg-agent.conf`.
 
 - `services.influxdb2` now supports doing an automatic initial setup and provisioning of users, organizations, buckets and authentication tokens, see [#249502](https://github.com/NixOS/nixpkgs/pull/249502) for more details.
@@ -237,6 +255,8 @@ The module update takes care of the new config syntax and the data itself (user
 - `networking.nftables` is no longer flushing all rulesets on every reload.
   Use `networking.nftables.flushRuleset = true;` to get back the old behaviour.
 
+- The `cawbird` package is dropped from nixpkgs, as it got broken by the Twitter API closing down and has been abandoned upstream.
+
 ## Nixpkgs internals {#sec-release-23.11-nixpkgs-internals}
 
 - 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.
diff --git a/nixpkgs/nixos/lib/testing/driver.nix b/nixpkgs/nixos/lib/testing/driver.nix
index 23574698c062..cc97ca72083f 100644
--- a/nixpkgs/nixos/lib/testing/driver.nix
+++ b/nixpkgs/nixos/lib/testing/driver.nix
@@ -175,7 +175,12 @@ in
   };
 
   config = {
-    _module.args.hostPkgs = config.hostPkgs;
+    _module.args = {
+      hostPkgs =
+        # Comment is in nixos/modules/misc/nixpkgs.nix
+        lib.mkOverride lib.modules.defaultOverridePriority
+          config.hostPkgs.__splicedPackages;
+    };
 
     driver = withChecks driver;
 
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
new file mode 100644
index 000000000000..7b743d170bc6
--- /dev/null
+++ b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image-inner.nix
@@ -0,0 +1,20 @@
+# Edit this configuration file to define what should be installed on
+# your system.  Help is available in the configuration.nix(5) man page
+# and in the NixOS manual (accessible by running ‘nixos-help’).
+
+{ config, pkgs, lib, ... }:
+
+{
+  imports =
+    [
+      # Include the default lxd configuration.
+      ../../../modules/virtualisation/lxc-container.nix
+      # Include the container-specific autogenerated configuration.
+      ./lxd.nix
+    ];
+
+  networking.useDHCP = false;
+  networking.interfaces.eth0.useDHCP = true;
+
+  system.stateVersion = "21.05"; # Did you read the comment?
+}
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-image.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image.nix
index 07605c5c3120..3bd1320b2b68 100644
--- a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-image.nix
+++ b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-container-image.nix
@@ -1,4 +1,4 @@
-{ lib, config, pkgs, ... }:
+{ lib, pkgs, ... }:
 
 {
   imports = [
@@ -16,8 +16,8 @@
   system.activationScripts.config = ''
     if [ ! -e /etc/nixos/configuration.nix ]; then
       mkdir -p /etc/nixos
-      cat ${./lxd-image-inner.nix} > /etc/nixos/configuration.nix
-      sed 's|../../../modules/virtualisation/lxc-container.nix|<nixpkgs/nixos/modules/virtualisation/lxc-container.nix>|g' -i /etc/nixos/configuration.nix
+      cat ${./lxd-container-image-inner.nix} > /etc/nixos/configuration.nix
+      ${lib.getExe pkgs.gnused} 's|../../../modules/virtualisation/lxc-container.nix|<nixpkgs/nixos/modules/virtualisation/lxc-container.nix>|g' -i /etc/nixos/configuration.nix
     fi
   '';
 
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-image-inner.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-image-inner.nix
deleted file mode 100644
index c1a9b1aacd18..000000000000
--- a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-image-inner.nix
+++ /dev/null
@@ -1,95 +0,0 @@
-# Edit this configuration file to define what should be installed on
-# your system.  Help is available in the configuration.nix(5) man page
-# and in the NixOS manual (accessible by running ‘nixos-help’).
-
-{ config, pkgs, lib, ... }:
-
-{
-  imports =
-    [ # Include the default lxd configuration.
-      ../../../modules/virtualisation/lxc-container.nix
-      # Include the container-specific autogenerated configuration.
-      ./lxd.nix
-    ];
-
-  # networking.hostName = mkForce "nixos"; # Overwrite the hostname.
-  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
-
-  # Set your time zone.
-  # time.timeZone = "Europe/Amsterdam";
-
-  # The global useDHCP flag is deprecated, therefore explicitly set to false here.
-  # Per-interface useDHCP will be mandatory in the future, so this generated config
-  # replicates the default behaviour.
-  networking.useDHCP = false;
-  networking.interfaces.eth0.useDHCP = true;
-
-  # Configure network proxy if necessary
-  # networking.proxy.default = "http://user:password@proxy:port/";
-  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
-
-  # Select internationalisation properties.
-  # i18n.defaultLocale = "en_US.UTF-8";
-  # console = {
-  #   font = "Lat2-Terminus16";
-  #   keyMap = "us";
-  # };
-
-  # Enable the X11 windowing system.
-  # services.xserver.enable = true;
-
-  # Configure keymap in X11
-  # services.xserver.layout = "us";
-  # services.xserver.xkbOptions = "eurosign:e";
-
-  # Enable CUPS to print documents.
-  # services.printing.enable = true;
-
-  # Enable sound.
-  # sound.enable = true;
-  # hardware.pulseaudio.enable = true;
-
-  # Enable touchpad support (enabled default in most desktopManager).
-  # services.xserver.libinput.enable = true;
-
-  # Define a user account. Don't forget to set a password with ‘passwd’.
-  # users.users.alice = {
-  #   isNormalUser = true;
-  #   extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
-  # };
-
-  # List packages installed in system profile. To search, run:
-  # $ nix search wget
-  # environment.systemPackages = with pkgs; [
-  #   vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
-  #   wget
-  #   firefox
-  # ];
-
-  # Some programs need SUID wrappers, can be configured further or are
-  # started in user sessions.
-  # programs.mtr.enable = true;
-  # programs.gnupg.agent = {
-  #   enable = true;
-  #   enableSSHSupport = true;
-  # };
-
-  # List services that you want to enable:
-
-  # Enable the OpenSSH daemon.
-  # services.openssh.enable = true;
-
-  # Open ports in the firewall.
-  # networking.firewall.allowedTCPPorts = [ ... ];
-  # networking.firewall.allowedUDPPorts = [ ... ];
-  # Or disable the firewall altogether.
-  # networking.firewall.enable = false;
-
-  # This value determines the NixOS release from which the default
-  # settings for stateful data, like file locations and database versions
-  # on your system were taken. It’s perfectly fine and recommended to leave
-  # this value at the release version of the first install of this system.
-  # Before changing this value read the documentation for this option
-  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
-  system.stateVersion = "21.05"; # Did you read the comment?
-}
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image-inner.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image-inner.nix
new file mode 100644
index 000000000000..a8f2c63ac5c6
--- /dev/null
+++ b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image-inner.nix
@@ -0,0 +1,20 @@
+# Edit this configuration file to define what should be installed on
+# your system.  Help is available in the configuration.nix(5) man page
+# and in the NixOS manual (accessible by running ‘nixos-help’).
+
+{ config, pkgs, lib, ... }:
+
+{
+  imports =
+    [
+      # Include the default lxd configuration.
+      ../../../modules/virtualisation/lxd-virtual-machine.nix
+      # Include the container-specific autogenerated configuration.
+      ./lxd.nix
+    ];
+
+  networking.useDHCP = false;
+  networking.interfaces.eth0.useDHCP = true;
+
+  system.stateVersion = "23.05"; # Did you read the comment?
+}
diff --git a/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix
new file mode 100644
index 000000000000..eb0d9217d402
--- /dev/null
+++ b/nixpkgs/nixos/maintainers/scripts/lxd/lxd-virtual-machine-image.nix
@@ -0,0 +1,27 @@
+{ lib, pkgs, ... }:
+
+{
+  imports = [
+    ../../../modules/virtualisation/lxd-virtual-machine.nix
+  ];
+
+  virtualisation.lxc.templates.nix = {
+    enable = true;
+    target = "/etc/nixos/lxd.nix";
+    template = ./nix.tpl;
+    when = ["create" "copy"];
+  };
+
+  # copy the config for nixos-rebuild
+  system.activationScripts.config = ''
+    if [ ! -e /etc/nixos/configuration.nix ]; then
+      mkdir -p /etc/nixos
+      cat ${./lxd-virtual-machine-image-inner.nix} > /etc/nixos/configuration.nix
+      ${lib.getExe pkgs.gnused} 's|../../../modules/virtualisation/lxd-virtual-machine.nix|<nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix>|g' -i /etc/nixos/configuration.nix
+    fi
+  '';
+
+  # Network
+  networking.useDHCP = false;
+  networking.interfaces.enp5s0.useDHCP = true;
+}
diff --git a/nixpkgs/nixos/modules/config/update-users-groups.pl b/nixpkgs/nixos/modules/config/update-users-groups.pl
index 5f6b65fcd1e1..4312197a3735 100644
--- a/nixpkgs/nixos/modules/config/update-users-groups.pl
+++ b/nixpkgs/nixos/modules/config/update-users-groups.pl
@@ -5,7 +5,7 @@ use File::Path qw(make_path);
 use File::Slurp;
 use Getopt::Long;
 use JSON;
-use DateTime;
+use Time::Piece;
 
 # Keep track of deleted uids and gids.
 my $uidMapFile = "/var/lib/nixos/uid-map";
@@ -27,17 +27,8 @@ sub updateFile {
 # Converts an ISO date to number of days since 1970-01-01
 sub dateToDays {
     my ($date) = @_;
-    my ($year, $month, $day) = split('-', $date, -3);
-    my $dt = DateTime->new(
-        year      => $year,
-        month     => $month,
-        day       => $day,
-        hour      => 0,
-        minute    => 0,
-        second    => 0,
-        time_zone => 'UTC',
-    );
-    return $dt->epoch / 86400;
+    my $time = Time::Piece->strptime($date, "%Y-%m-%d");
+    return $time->epoch / 60 / 60 / 24;
 }
 
 sub nscdInvalidate {
diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix
index 9629e3964c96..684b4bc8fbcc 100644
--- a/nixpkgs/nixos/modules/config/users-groups.nix
+++ b/nixpkgs/nixos/modules/config/users-groups.nix
@@ -648,7 +648,7 @@ in {
         install -m 0700 -d /root
         install -m 0755 -d /home
 
-        ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON p.DateTime ])}/bin/perl \
+        ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON ])}/bin/perl \
         -w ${./update-users-groups.pl} ${spec}
       '';
     };
diff --git a/nixpkgs/nixos/modules/hardware/infiniband.nix b/nixpkgs/nixos/modules/hardware/infiniband.nix
new file mode 100644
index 000000000000..962883fa7972
--- /dev/null
+++ b/nixpkgs/nixos/modules/hardware/infiniband.nix
@@ -0,0 +1,58 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.hardware.infiniband;
+  opensm-services = {
+    "opensm@" = {
+      enable = true;
+      description = "Starts OpenSM Infiniband fabric Subnet Managers";
+      before = [ "network.target"];
+      unitConfig = {
+        ConditionPathExists = "/sys/class/infiniband_mad/abi_version";
+      };
+      serviceConfig = {
+        Type = "simple";
+        ExecStart = "${pkgs.opensm}/bin/opensm --guid %I --log_file /var/log/opensm.%I.log";
+      };
+    };
+  } // (builtins.listToAttrs (map (guid: {
+    name = "opensm@${guid}";
+    value = {
+      enable = true;
+      wantedBy = [ "machines.target" ];
+      overrideStrategy = "asDropin";
+    };
+  } ) cfg.guids));
+
+in
+
+{
+  options.hardware.infiniband = {
+    enable = mkEnableOption "Infiniband support";
+    guids = mkOption {
+      type = with types; listOf str;
+      default = [];
+      example = [ "0xe8ebd30000eee2e1" ];
+      description = lib.mdDoc ''
+        A list of infiniband port guids on the system. This is discoverable using `ibstat -p`
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    boot.initrd.kernelModules = [
+      "mlx5_core" "mlx5_ib" "ib_cm"
+      "rdma_cm" "rdma_ucm" "rpcrdma"
+      "ib_ipoib" "ib_isert" "ib_umad" "ib_uverbs"
+    ];
+    # rdma-core exposes ibstat, mstflint exposes mstconfig (which can be needed for
+    # setting link configurations), qperf needed to affirm link speeds
+    environment.systemPackages = with pkgs; [
+      rdma-core mstflint qperf
+    ];
+    systemd.services = opensm-services;
+  };
+}
diff --git a/nixpkgs/nixos/modules/i18n/input-method/uim.nix b/nixpkgs/nixos/modules/i18n/input-method/uim.nix
index 9491ab2640fc..7225783b2a6f 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/uim.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/uim.nix
@@ -10,7 +10,7 @@ in
 
     i18n.inputMethod.uim = {
       toolbar = mkOption {
-        type    = types.enum [ "gtk" "gtk3" "gtk-systray" "gtk3-systray" "qt4" ];
+        type    = types.enum [ "gtk" "gtk3" "gtk-systray" "gtk3-systray" "qt5" ];
         default = "gtk";
         example = "gtk-systray";
         description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
index ea8056ff870c..573b31b439c2 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
@@ -6,7 +6,6 @@
   imports = [ ./installation-cd-graphical-base.nix ];
 
   isoImage.edition = "gnome";
-  isoImage.graphicalGrub = true;
 
   services.xserver.desktopManager.gnome = {
     # Add Firefox and other tools useful for installation to the launcher
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
index c430048d6598..0b5135c088ea 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -24,6 +24,9 @@ let
         # Name appended to menuentry defaults to params if no specific name given.
         option.name or (optionalString (option ? params) "(${option.params})")
         }' ${optionalString (option ? class) " --class ${option.class}"} {
+          # Fallback to UEFI console for boot, efifb sometimes has difficulties.
+          terminal_output console
+
           linux ${defaults.image} \''${isoboot} ${defaults.params} ${
             option.params or ""
           }
@@ -185,33 +188,25 @@ let
       # So instead we'll list a lot of possibly valid modes :/
       #"3840x2160"
       #"2560x1440"
+      "1920x1200"
       "1920x1080"
       "1366x768"
+      "1280x800"
       "1280x720"
+      "1200x1920"
       "1024x768"
+      "800x1280"
       "800x600"
       "auto"
     ]}
 
-    # Fonts can be loaded?
-    # (This font is assumed to always be provided as a fallback by NixOS)
-    if loadfont (\$root)/EFI/boot/unicode.pf2; then
-      set with_fonts=true
-    fi
-    if [ "\$textmode" != "true" -a "\$with_fonts" == "true" ]; then
-      # Use graphical term, it can be either with background image or a theme.
-      # input is "console", while output is "gfxterm".
-      # This enables "serial" input and output only when possible.
-      # Otherwise the failure mode is to not even enable gfxterm.
-      if test "\$with_serial" == "yes"; then
-        terminal_output gfxterm serial
-        terminal_input  console serial
-      else
-        terminal_output gfxterm
-        terminal_input  console
-      fi
+    if [ "\$textmode" == "false" ]; then
+      terminal_output gfxterm
+      terminal_input  console
     else
-      # Sets colors for the non-graphical term.
+      terminal_output console
+      terminal_input  console
+      # Sets colors for console term.
       set menu_color_normal=cyan/blue
       set menu_color_highlight=white/blue
     fi
@@ -250,18 +245,58 @@ let
     touch $out/EFI/nixos-installer-image
 
     # ALWAYS required modules.
-    MODULES="fat iso9660 part_gpt part_msdos \
-             normal boot linux configfile loopback chain halt \
-             efifwsetup efi_gop \
-             ls search search_label search_fs_uuid search_fs_file \
-             gfxmenu gfxterm gfxterm_background gfxterm_menu test all_video loadenv \
-             exfat ext2 ntfs btrfs hfsplus udf \
-             videoinfo png \
-             echo serial \
-            "
+    MODULES=(
+      # Basic modules for filesystems and partition schemes
+      "fat"
+      "iso9660"
+      "part_gpt"
+      "part_msdos"
+
+      # Basic stuff
+      "normal"
+      "boot"
+      "linux"
+      "configfile"
+      "loopback"
+      "chain"
+      "halt"
+
+      # Allows rebooting into firmware setup interface
+      "efifwsetup"
+
+      # EFI Graphics Output Protocol
+      "efi_gop"
+
+      # User commands
+      "ls"
+
+      # System commands
+      "search"
+      "search_label"
+      "search_fs_uuid"
+      "search_fs_file"
+      "echo"
+
+      # We're not using it anymore, but we'll leave it in so it can be used
+      # by user, with the console using "C"
+      "serial"
+
+      # Graphical mode stuff
+      "gfxmenu"
+      "gfxterm"
+      "gfxterm_background"
+      "gfxterm_menu"
+      "test"
+      "loadenv"
+      "all_video"
+      "videoinfo"
+
+      # File types for graphical mode
+      "png"
+    )
 
     echo "Building GRUB with modules:"
-    for mod in $MODULES; do
+    for mod in ''${MODULES[@]}; do
       echo " - $mod"
     done
 
@@ -270,31 +305,27 @@ let
     for mod in efi_uga; do
       if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then
         echo " - $mod"
-        MODULES+=" $mod"
+        MODULES+=("$mod")
       fi
     done
 
     # Make our own efi program, we can't rely on "grub-install" since it seems to
     # probe for devices, even with --skip-fs-probe.
-    grub-mkimage --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
-      $MODULES
+    grub-mkimage \
+      --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} \
+      -o $out/EFI/boot/boot${targetArch}.efi \
+      -p /EFI/boot \
+      -O ${grubPkgs.grub2_efi.grubTarget} \
+      ''${MODULES[@]}
     cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
 
     cat <<EOF > $out/EFI/boot/grub.cfg
 
-    set with_fonts=false
-    set textmode=${boolToString (!config.isoImage.graphicalGrub)}
-    # If you want to use serial for "terminal_*" commands, you need to set one up:
-    #   Example manual configuration:
-    #    → serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
-    # This uses the defaults, and makes the serial terminal available.
-    set with_serial=no
-    if serial; then set with_serial=yes ;fi
-    export with_serial
-    clear
+    set textmode=${boolToString (config.isoImage.forceTextMode)}
     set timeout=${toString grubEfiTimeout}
 
-    # This message will only be viewable when "gfxterm" is not used.
+    clear
+    # This message will only be viewable on the default (UEFI) console.
     echo ""
     echo "Loading graphical boot menu..."
     echo ""
@@ -306,7 +337,7 @@ let
     hiddenentry 'Text mode' --hotkey 't' {
       loadfont (\$root)/EFI/boot/unicode.pf2
       set textmode=true
-      terminal_output gfxterm console
+      terminal_output console
     }
     hiddenentry 'GUI mode' --hotkey 'g' {
       $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
@@ -400,6 +431,8 @@ let
     }
     EOF
 
+    grub-script-check $out/EFI/boot/grub.cfg
+
     ${refind}
   '';
 
@@ -658,13 +691,17 @@ in
       '';
     };
 
-    isoImage.graphicalGrub = mkOption {
+    isoImage.forceTextMode = mkOption {
       default = false;
       type = types.bool;
       example = true;
       description = lib.mdDoc ''
-        Whether to use textmode or graphical grub.
-        false means we use textmode grub.
+        Whether to use text mode instead of graphical grub.
+        A value of `true` means graphical mode is not tried to be used.
+
+        This is useful for validating that graphics mode usage is not at the root cause of a problem with the iso image.
+
+        If text mode is required off-handedly (e.g. for serial use) you can use the `T` key, after being prompted, to use text mode for the current boot.
       '';
     };
 
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index dc4eb41bcddf..9e5d417046b8 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -63,6 +63,7 @@
   ./hardware/gpgsmartcards.nix
   ./hardware/hackrf.nix
   ./hardware/i2c.nix
+  ./hardware/infiniband.nix
   ./hardware/keyboard/qmk.nix
   ./hardware/keyboard/teck.nix
   ./hardware/keyboard/uhk.nix
@@ -163,6 +164,7 @@
   ./programs/direnv.nix
   ./programs/dmrconfig.nix
   ./programs/droidcam.nix
+  ./programs/ecryptfs.nix
   ./programs/environment.nix
   ./programs/evince.nix
   ./programs/extra-container.nix
@@ -595,6 +597,7 @@
   ./services/mail/rss2email.nix
   ./services/mail/schleuder.nix
   ./services/mail/spamassassin.nix
+  ./services/mail/stalwart-mail.nix
   ./services/mail/sympa.nix
   ./services/mail/zeyple.nix
   ./services/matrix/appservice-discord.nix
@@ -1259,6 +1262,7 @@
   ./services/web-apps/node-red.nix
   ./services/web-apps/onlyoffice.nix
   ./services/web-apps/openvscode-server.nix
+  ./services/web-apps/mobilizon.nix
   ./services/web-apps/openwebrx.nix
   ./services/web-apps/outline.nix
   ./services/web-apps/peering-manager.nix
diff --git a/nixpkgs/nixos/modules/programs/ecryptfs.nix b/nixpkgs/nixos/modules/programs/ecryptfs.nix
new file mode 100644
index 000000000000..63c1a3ad4419
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/ecryptfs.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.ecryptfs;
+
+in {
+  options.programs.ecryptfs = {
+    enable = mkEnableOption (lib.mdDoc "ecryptfs setuid mount wrappers");
+  };
+
+  config = mkIf cfg.enable {
+    security.wrappers = {
+
+      "mount.ecryptfs_private" = {
+        setuid = true;
+        owner = "root";
+        group = "root";
+        source = "${lib.getBin pkgs.ecryptfs}/bin/mount.ecryptfs_private";
+      };
+      "umount.ecryptfs_private" = {
+        setuid = true;
+        owner = "root";
+        group = "root";
+        source = "${lib.getBin pkgs.ecryptfs}/bin/umount.ecryptfs_private";
+      };
+
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/streamdeck-ui.nix b/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
index 4c055029e39b..220f0a35f162 100644
--- a/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
+++ b/nixpkgs/nixos/modules/programs/streamdeck-ui.nix
@@ -24,7 +24,7 @@ in
   config = mkIf cfg.enable {
     environment.systemPackages = with pkgs; [
       cfg.package
-      (mkIf cfg.autoStart (makeAutostartItem { name = "streamdeck-ui"; package = cfg.package; }))
+      (mkIf cfg.autoStart (makeAutostartItem { name = "streamdeck-ui-noui"; package = cfg.package; }))
     ];
 
     services.udev.packages = [ cfg.package ];
diff --git a/nixpkgs/nixos/modules/programs/yazi.nix b/nixpkgs/nixos/modules/programs/yazi.nix
new file mode 100644
index 000000000000..3416bca06679
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/yazi.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.programs.yazi;
+
+  settingsFormat = pkgs.formats.toml { };
+
+  names = [ "yazi" "theme" "keymap" ];
+in
+{
+  options.programs.yazi = {
+    enable = lib.mkEnableOption (lib.mdDoc "yazi terminal file manager");
+
+    package = lib.mkPackageOptionMD pkgs "yazi" { };
+
+    settings = lib.mkOption {
+      type = with lib.types; submodule {
+        options = lib.listToAttrs (map
+          (name: lib.nameValuePair name (lib.mkOption {
+            inherit (settingsFormat) type;
+            default = { };
+            description = lib.mdDoc ''
+              Configuration included in `${name}.toml`.
+
+              See https://github.com/sxyazi/yazi/blob/v${cfg.package.version}/config/docs/${name}.md for documentation.
+            '';
+          }))
+          names);
+      };
+      default = { };
+      description = lib.mdDoc ''
+        Configuration included in `$YAZI_CONFIG_HOME`.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment = {
+      systemPackages = [ cfg.package ];
+      variables.YAZI_CONFIG_HOME = "/etc/yazi/";
+      etc = lib.attrsets.mergeAttrsList (map
+        (name: lib.optionalAttrs (cfg.settings.${name} != { }) {
+          "yazi/${name}.toml".source = settingsFormat.generate "${name}.toml" cfg.settings.${name};
+        })
+        names);
+    };
+  };
+  meta.maintainers = with lib.maintainers; [ linsui ];
+}
diff --git a/nixpkgs/nixos/modules/security/sudo.nix b/nixpkgs/nixos/modules/security/sudo.nix
index 9ac91bd0d368..d225442773c6 100644
--- a/nixpkgs/nixos/modules/security/sudo.nix
+++ b/nixpkgs/nixos/modules/security/sudo.nix
@@ -192,6 +192,10 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
+    assertions = [
+      { assertion = cfg.package.pname != "sudo-rs";
+        message = "The NixOS `sudo` module does not work with `sudo-rs` yet."; }
+    ];
 
     # We `mkOrder 600` so that the default rule shows up first, but there is
     # still enough room for a user to `mkBefore` it.
diff --git a/nixpkgs/nixos/modules/services/backup/duplicati.nix b/nixpkgs/nixos/modules/services/backup/duplicati.nix
index 007396ebfc9b..9b422635e7f0 100644
--- a/nixpkgs/nixos/modules/services/backup/duplicati.nix
+++ b/nixpkgs/nixos/modules/services/backup/duplicati.nix
@@ -10,6 +10,8 @@ in
     services.duplicati = {
       enable = mkEnableOption (lib.mdDoc "Duplicati");
 
+      package = mkPackageOptionMD pkgs "duplicati" { };
+
       port = mkOption {
         default = 8200;
         type = types.port;
@@ -53,7 +55,7 @@ in
   };
 
   config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.duplicati ];
+    environment.systemPackages = [ cfg.package ];
 
     systemd.services.duplicati = {
       description = "Duplicati backup";
@@ -63,7 +65,7 @@ in
         {
           User = cfg.user;
           Group = "duplicati";
-          ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=${cfg.dataDir}";
+          ExecStart = "${cfg.package}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=${cfg.dataDir}";
           Restart = "on-failure";
         }
         (mkIf (cfg.dataDir == "/var/lib/duplicati") {
@@ -83,4 +85,3 @@ in
 
   };
 }
-
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
index ce8809213724..f2887c7711b3 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/options.nix
@@ -208,4 +208,12 @@ with lib;
     '';
     default = null;
   };
+
+  nodeRuntimes = mkOption {
+    type = with types; nonEmptyListOf (enum [ "node16" "node20" ]);
+    default = [ "node20" ];
+    description = mdDoc ''
+      List of Node.js runtimes the runner should support.
+    '';
+  };
 }
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/service.nix b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/service.nix
index 55df83362cb6..535df7f68e07 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/github-runner/service.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/github-runner/service.nix
@@ -22,6 +22,7 @@ with lib;
 
 let
   workDir = if cfg.workDir == null then runtimeDir else cfg.workDir;
+  package = cfg.package.override { inherit (cfg) nodeRuntimes; };
 in
 {
   description = "GitHub Actions runner";
@@ -47,7 +48,7 @@ in
 
   serviceConfig = mkMerge [
     {
-      ExecStart = "${cfg.package}/bin/Runner.Listener run --startuptype service";
+      ExecStart = "${package}/bin/Runner.Listener run --startuptype service";
 
       # Does the following, sequentially:
       # - If the module configuration or the token has changed, purge the state directory,
@@ -149,7 +150,7 @@ in
               else
                 args+=(--token "$token")
               fi
-              ${cfg.package}/bin/Runner.Listener configure "''${args[@]}"
+              ${package}/bin/Runner.Listener configure "''${args[@]}"
               # Move the automatically created _diag dir to the logs dir
               mkdir -p  "$STATE_DIRECTORY/_diag"
               cp    -r  "$STATE_DIRECTORY/_diag/." "$LOGS_DIRECTORY/"
diff --git a/nixpkgs/nixos/modules/services/databases/surrealdb.nix b/nixpkgs/nixos/modules/services/databases/surrealdb.nix
index 050a5336cb4c..28bd97cd731e 100644
--- a/nixpkgs/nixos/modules/services/databases/surrealdb.nix
+++ b/nixpkgs/nixos/modules/services/databases/surrealdb.nix
@@ -47,17 +47,13 @@ in {
         example = 8000;
       };
 
-      userNamePath = mkOption {
-        type = types.path;
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "--allow-all" "--auth" "--user root" "--pass root" ];
         description = lib.mdDoc ''
-          Path to read the username from.
-        '';
-      };
-
-      passwordPath = mkOption {
-        type = types.path;
-        description = lib.mdDoc ''
-          Path to read the password from.
+          Specify a list of additional command line flags,
+          which get escaped and are then passed to surrealdb.
         '';
       };
     };
@@ -73,19 +69,8 @@ in {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
-      script = ''
-        ${cfg.package}/bin/surreal start \
-          --user $(${pkgs.systemd}/bin/systemd-creds cat SURREALDB_USERNAME) \
-          --pass $(${pkgs.systemd}/bin/systemd-creds cat SURREALDB_PASSWORD) \
-          --bind ${cfg.host}:${toString cfg.port} \
-          -- ${cfg.dbPath}
-      '';
       serviceConfig = {
-        LoadCredential = [
-          "SURREALDB_USERNAME:${cfg.userNamePath}"
-          "SURREALDB_PASSWORD:${cfg.passwordPath}"
-        ];
-
+        ExecStart = "${cfg.package}/bin/surreal start --bind ${cfg.host}:${toString cfg.port} ${escapeShellArgs cfg.extraFlags} -- ${cfg.dbPath}";
         DynamicUser = true;
         Restart = "on-failure";
         StateDirectory = "surrealdb";
diff --git a/nixpkgs/nixos/modules/services/hardware/auto-cpufreq.nix b/nixpkgs/nixos/modules/services/hardware/auto-cpufreq.nix
index fd2e03ef12f5..cf27bdd8b6eb 100644
--- a/nixpkgs/nixos/modules/services/hardware/auto-cpufreq.nix
+++ b/nixpkgs/nixos/modules/services/hardware/auto-cpufreq.nix
@@ -15,8 +15,7 @@ in {
         description = lib.mdDoc ''
           Configuration for `auto-cpufreq`.
 
-          See its [example configuration file] for supported settings.
-          [example configuration file]: https://github.com/AdnanHodzic/auto-cpufreq/blob/master/auto-cpufreq.conf-example
+          The available options can be found in [the example configuration file](https://github.com/AdnanHodzic/auto-cpufreq/blob/v${pkgs.auto-cpufreq.version}/auto-cpufreq.conf-example).
           '';
 
         default = {};
@@ -35,6 +34,7 @@ in {
         wantedBy = [ "multi-user.target" ];
         path = with pkgs; [ bash coreutils ];
 
+        serviceConfig.WorkingDirectory = "";
         serviceConfig.ExecStart = [
           ""
           "${lib.getExe pkgs.auto-cpufreq} --daemon --config ${cfgFile}"
@@ -42,4 +42,7 @@ in {
       };
     };
   };
+
+  # uses attributes of the linked package
+  meta.buildDocsInSandbox = false;
 }
diff --git a/nixpkgs/nixos/modules/services/hardware/openrgb.nix b/nixpkgs/nixos/modules/services/hardware/openrgb.nix
index 310615ecc539..13b1d07e53b7 100644
--- a/nixpkgs/nixos/modules/services/hardware/openrgb.nix
+++ b/nixpkgs/nixos/modules/services/hardware/openrgb.nix
@@ -17,7 +17,14 @@ in {
 
     motherboard = mkOption {
       type = types.nullOr (types.enum [ "amd" "intel" ]);
-      default = null;
+      default = if config.hardware.cpu.intel.updateMicrocode then "intel"
+        else if config.hardware.cpu.amd.updateMicrocode then "amd"
+        else null;
+      defaultText = literalMD ''
+        if config.hardware.cpu.intel.updateMicrocode then "intel"
+        else if config.hardware.cpu.amd.updateMicrocode then "amd"
+        else null;
+      '';
       description = lib.mdDoc "CPU family of motherboard. Allows for addition motherboard i2c support.";
     };
 
diff --git a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
new file mode 100644
index 000000000000..fdbdc99070b9
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
@@ -0,0 +1,106 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.stalwart-mail;
+  configFormat = pkgs.formats.toml { };
+  configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
+  dataDir = "/var/lib/stalwart-mail";
+
+in {
+  options.services.stalwart-mail = {
+    enable = mkEnableOption (mdDoc "the Stalwart all-in-one email server");
+    package = mkPackageOptionMD pkgs "stalwart-mail" { };
+
+    settings = mkOption {
+      inherit (configFormat) type;
+      default = { };
+      description = mdDoc ''
+        Configuration options for the Stalwart email server.
+        See <https://stalw.art/docs/> for available options.
+
+        By default, the module is configured to store everything locally.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    # Default config: all local
+    services.stalwart-mail.settings = {
+      global.tracing.method = mkDefault "stdout";
+      global.tracing.level = mkDefault "info";
+      queue.path = mkDefault "${dataDir}/queue";
+      report.path = mkDefault "${dataDir}/reports";
+      store.db.path = mkDefault "${dataDir}/data/index.sqlite3";
+      store.blob.type = mkDefault "local";
+      store.blob.local.path = mkDefault "${dataDir}/data/blobs";
+      resolver.type = mkDefault "system";
+    };
+
+    systemd.services.stalwart-mail = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "local-fs.target" "network.target" ];
+
+      preStart = ''
+        mkdir -p ${dataDir}/{queue,reports,data/blobs}
+      '';
+
+      serviceConfig = {
+        ExecStart =
+          "${cfg.package}/bin/stalwart-mail --config=${configFile}";
+
+        # Base from template resources/systemd/stalwart-mail.service
+        Type = "simple";
+        LimitNOFILE = 65536;
+        KillMode = "process";
+        KillSignal = "SIGINT";
+        Restart = "on-failure";
+        RestartSec = 5;
+        StandardOutput = "syslog";
+        StandardError = "syslog";
+        SyslogIdentifier = "stalwart-mail";
+
+        DynamicUser = true;
+        User = "stalwart-mail";
+        StateDirectory = "stalwart-mail";
+
+        # Bind standard privileged ports
+        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+        CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+
+        # Hardening
+        DeviceAllow = [ "" ];
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        PrivateDevices = true;
+        PrivateUsers = false;  # incompatible with CAP_NET_BIND_SERVICE
+        ProcSubset = "pid";
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [ "@system-service" "~@privileged" ];
+        UMask = "0077";
+      };
+    };
+
+    # Make admin commands available in the shell
+    environment.systemPackages = [ cfg.package ];
+  };
+
+  meta = {
+    maintainers = with maintainers; [ happysalada pacien ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/matrix/mautrix-telegram.nix b/nixpkgs/nixos/modules/services/matrix/mautrix-telegram.nix
index 17032ed808e9..97a6ba858e00 100644
--- a/nixpkgs/nixos/modules/services/matrix/mautrix-telegram.nix
+++ b/nixpkgs/nixos/modules/services/matrix/mautrix-telegram.nix
@@ -159,7 +159,6 @@ in {
         if [ ! -f '${registrationFile}' ]; then
           ${pkgs.mautrix-telegram}/bin/mautrix-telegram \
             --generate-registration \
-            --base-config='${pkgs.mautrix-telegram}/${pkgs.mautrix-telegram.pythonModule.sitePackages}/mautrix_telegram/example-config.yaml' \
             --config='${settingsFile}' \
             --registration='${registrationFile}'
         fi
diff --git a/nixpkgs/nixos/modules/services/matrix/mautrix-whatsapp.nix b/nixpkgs/nixos/modules/services/matrix/mautrix-whatsapp.nix
index 80c85980196f..c4dc48213495 100644
--- a/nixpkgs/nixos/modules/services/matrix/mautrix-whatsapp.nix
+++ b/nixpkgs/nixos/modules/services/matrix/mautrix-whatsapp.nix
@@ -11,53 +11,47 @@
   settingsFileUnsubstituted = settingsFormat.generate "mautrix-whatsapp-config-unsubstituted.json" cfg.settings;
   settingsFormat = pkgs.formats.json {};
   appservicePort = 29318;
+
+  mkDefaults = lib.mapAttrsRecursive (n: v: lib.mkDefault v);
+  defaultConfig = {
+    homeserver.address = "http://localhost:8448";
+    appservice = {
+      hostname = "[::]";
+      port = appservicePort;
+      database.type = "sqlite3";
+      database.uri = "${dataDir}/mautrix-whatsapp.db";
+      id = "whatsapp";
+      bot.username = "whatsappbot";
+      bot.displayname = "WhatsApp Bridge Bot";
+      as_token = "";
+      hs_token = "";
+    };
+    bridge = {
+      username_template = "whatsapp_{{.}}";
+      displayname_template = "{{if .BusinessName}}{{.BusinessName}}{{else if .PushName}}{{.PushName}}{{else}}{{.JID}}{{end}} (WA)";
+      double_puppet_server_map = {};
+      login_shared_secret_map = {};
+      command_prefix = "!wa";
+      permissions."*" = "relay";
+      relay.enabled = true;
+    };
+    logging = {
+      min_level = "info";
+      writers = lib.singleton {
+        type = "stdout";
+        format = "pretty-colored";
+        time_format = " ";
+      };
+    };
+  };
+
 in {
-  imports = [];
   options.services.mautrix-whatsapp = {
-    enable = lib.mkEnableOption "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp.";
+    enable = lib.mkEnableOption (lib.mdDoc "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp.");
 
     settings = lib.mkOption {
       type = settingsFormat.type;
-      default = {
-        appservice = {
-          address = "http://localhost:${toString appservicePort}";
-          hostname = "[::]";
-          port = appservicePort;
-          database = {
-            type = "sqlite3";
-            uri = "${dataDir}/mautrix-whatsapp.db";
-          };
-          id = "whatsapp";
-          bot = {
-            username = "whatsappbot";
-            displayname = "WhatsApp Bridge Bot";
-          };
-          as_token = "";
-          hs_token = "";
-        };
-        bridge = {
-          username_template = "whatsapp_{{.}}";
-          displayname_template = "{{if .BusinessName}}{{.BusinessName}}{{else if .PushName}}{{.PushName}}{{else}}{{.JID}}{{end}} (WA)";
-          double_puppet_server_map = {};
-          login_shared_secret_map = {};
-          command_prefix = "!wa";
-          permissions."*" = "relay";
-          relay.enabled = true;
-        };
-        logging = {
-          min_level = "info";
-          writers = [
-            {
-              type = "stdout";
-              format = "pretty-colored";
-            }
-            {
-              type = "file";
-              format = "json";
-            }
-          ];
-        };
-      };
+      default = defaultConfig;
       description = lib.mdDoc ''
         {file}`config.yaml` configuration as a Nix attribute set.
         Configuration options should match those described in
@@ -117,10 +111,22 @@ in {
   };
 
   config = lib.mkIf cfg.enable {
-    services.mautrix-whatsapp.settings = {
-      homeserver.domain = lib.mkDefault config.services.matrix-synapse.settings.server_name;
+
+    users.users.mautrix-whatsapp = {
+      isSystemUser = true;
+      group = "mautrix-whatsapp";
+      home = dataDir;
+      description = "Mautrix-WhatsApp bridge user";
     };
 
+    users.groups.mautrix-whatsapp = {};
+
+    services.mautrix-whatsapp.settings = lib.mkMerge (map mkDefaults [
+      defaultConfig
+      # Note: this is defined here to avoid the docs depending on `config`
+      { homeserver.domain = config.services.matrix-synapse.settings.server_name; }
+    ]);
+
     systemd.services.mautrix-whatsapp = {
       description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix";
 
@@ -158,10 +164,11 @@ in {
       '';
 
       serviceConfig = {
-        DynamicUser = true;
+        User = "mautrix-whatsapp";
+        Group = "mautrix-whatsapp";
         EnvironmentFile = cfg.environmentFile;
         StateDirectory = baseNameOf dataDir;
-        WorkingDirectory = "${dataDir}";
+        WorkingDirectory = dataDir;
         ExecStart = ''
           ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp \
           --config='${settingsFile}' \
diff --git a/nixpkgs/nixos/modules/services/misc/atuin.nix b/nixpkgs/nixos/modules/services/misc/atuin.nix
index 57ff02df7d68..8d2c1b5242ff 100644
--- a/nixpkgs/nixos/modules/services/misc/atuin.nix
+++ b/nixpkgs/nixos/modules/services/misc/atuin.nix
@@ -6,7 +6,7 @@ in
 {
   options = {
     services.atuin = {
-      enable = lib.mkEnableOption (mdDoc "Enable server for shell history sync with atuin");
+      enable = lib.mkEnableOption (mdDoc "Atuin server for shell history sync");
 
       openRegistration = mkOption {
         type = types.bool;
diff --git a/nixpkgs/nixos/modules/services/misc/gitlab.nix b/nixpkgs/nixos/modules/services/misc/gitlab.nix
index c5e38b498829..b399ccc38f58 100644
--- a/nixpkgs/nixos/modules/services/misc/gitlab.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitlab.nix
@@ -1088,6 +1088,11 @@ in {
         ''Support for container registries other than gitlab-container-registry has ended since GitLab 16.0.0 and is scheduled for removal in a future release.
           Please back up your data and migrate to the gitlab-container-registry package.''
       )
+      (mkIf
+        (versionAtLeast (getVersion cfg.packages.gitlab) "16.2.0" && versionOlder (getVersion cfg.packages.gitlab) "16.5.0")
+        ''GitLab instances created or updated between versions [15.11.0, 15.11.2] have an incorrect database schema.
+        Check the upstream documentation for a workaround: https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html#undefined-column-error-upgrading-to-162-or-later''
+      )
     ];
 
     assertions = [
@@ -1655,7 +1660,7 @@ in {
         Restart = "on-failure";
         WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
         ExecStart = concatStringsSep " " [
-          "${cfg.packages.gitlab.rubyEnv}/bin/puma"
+          "${cfg.packages.gitlab.rubyEnv}/bin/bundle" "exec" "puma"
           "-e production"
           "-C ${cfg.statePath}/config/puma.rb"
           "-w ${cfg.puma.workers}"
diff --git a/nixpkgs/nixos/modules/services/monitoring/mimir.nix b/nixpkgs/nixos/modules/services/monitoring/mimir.nix
index edca9b7be4ff..6ed139b22974 100644
--- a/nixpkgs/nixos/modules/services/monitoring/mimir.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/mimir.nix
@@ -32,11 +32,21 @@ in {
       type = types.package;
       description = lib.mdDoc ''Mimir package to use.'';
     };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "--config.expand-env=true" ];
+      description = lib.mdDoc ''
+        Specify a list of additional command line flags,
+        which get escaped and are then passed to Mimir.
+      '';
+    };
   };
 
   config = mkIf cfg.enable {
     # for mimirtool
-    environment.systemPackages = [ pkgs.mimir ];
+    environment.systemPackages = [ cfg.package ];
 
     assertions = [{
       assertion = (
@@ -60,7 +70,7 @@ in {
                else cfg.configFile;
       in
       {
-        ExecStart = "${cfg.package}/bin/mimir --config.file=${conf}";
+        ExecStart = "${cfg.package}/bin/mimir --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
         DynamicUser = true;
         Restart = "always";
         ProtectSystem = "full";
diff --git a/nixpkgs/nixos/modules/services/networking/dae.nix b/nixpkgs/nixos/modules/services/networking/dae.nix
index 231c555b3303..42ed3c7f8d4a 100644
--- a/nixpkgs/nixos/modules/services/networking/dae.nix
+++ b/nixpkgs/nixos/modules/services/networking/dae.nix
@@ -1,41 +1,161 @@
-{ config, pkgs, lib, ... }:
+{ config, lib, pkgs, ... }:
+
 let
   cfg = config.services.dae;
+  assets = cfg.assets;
+  genAssetsDrv = paths: pkgs.symlinkJoin {
+    name = "dae-assets";
+    inherit paths;
+  };
 in
 {
-  meta.maintainers = with lib.maintainers; [ pokon548 ];
+  meta.maintainers = with lib.maintainers; [ pokon548 oluceps ];
 
   options = {
-    services.dae = {
-      enable = lib.options.mkEnableOption (lib.mdDoc "the dae service");
-      package = lib.mkPackageOptionMD pkgs "dae" { };
+    services.dae = with lib;{
+      enable = mkEnableOption
+        (mdDoc "A Linux high-performance transparent proxy solution based on eBPF");
+
+      package = mkPackageOptionMD pkgs "dae" { };
+
+      assets = mkOption {
+        type = with types;(listOf path);
+        default = with pkgs; [ v2ray-geoip v2ray-domain-list-community ];
+        defaultText = literalExpression "with pkgs; [ v2ray-geoip v2ray-domain-list-community ]";
+        description = mdDoc ''
+          Assets required to run dae.
+        '';
+      };
+
+      assetsPath = mkOption {
+        type = types.str;
+        default = "${genAssetsDrv assets}/share/v2ray";
+        defaultText = literalExpression ''
+          (symlinkJoin {
+              name = "dae-assets";
+              paths = assets;
+          })/share/v2ray
+        '';
+        description = mdDoc ''
+          The path which contains geolocation database.
+          This option will override `assets`.
+        '';
+      };
+
+      openFirewall = mkOption {
+        type = with types; submodule {
+          options = {
+            enable = mkEnableOption "enable";
+            port = mkOption {
+              type = types.int;
+              description = ''
+                Port to be opened. Consist with field `tproxy_port` in config file.
+              '';
+            };
+          };
+        };
+        default = {
+          enable = true;
+          port = 12345;
+        };
+        defaultText = literalExpression ''
+          {
+            enable = true;
+            port = 12345;
+          }
+        '';
+        description = mdDoc ''
+          Open the firewall port.
+        '';
+      };
+
+      configFile = mkOption {
+        type = types.path;
+        default = "/etc/dae/config.dae";
+        example = "/path/to/your/config.dae";
+        description = mdDoc ''
+          The path of dae config file, end with `.dae`.
+        '';
+      };
+
+      config = mkOption {
+        type = types.str;
+        default = ''
+          global{}
+          routing{}
+        '';
+        description = mdDoc ''
+          Config text for dae.
+
+          See <https://github.com/daeuniverse/dae/blob/main/example.dae>.
+        '';
+      };
+
+      disableTxChecksumIpGeneric =
+        mkEnableOption (mdDoc "See <https://github.com/daeuniverse/dae/issues/43>");
+
     };
   };
 
-  config = lib.mkIf config.services.dae.enable {
-    networking.firewall.allowedTCPPorts = [ 12345 ];
-    networking.firewall.allowedUDPPorts = [ 12345 ];
+  config = lib.mkIf cfg.enable
+
+    {
+      environment.systemPackages = [ cfg.package ];
+      systemd.packages = [ cfg.package ];
 
-    systemd.services.dae = {
-      unitConfig = {
-        Description = "dae Service";
-        Documentation = "https://github.com/daeuniverse/dae";
-        After = [ "network-online.target" "systemd-sysctl.service" ];
-        Wants = [ "network-online.target" ];
+      environment.etc."dae/config.dae" = {
+        mode = "0400";
+        source = pkgs.writeText "config.dae" cfg.config;
       };
 
-      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";
+      networking = lib.mkIf cfg.openFirewall.enable {
+        firewall =
+          let portToOpen = cfg.openFirewall.port;
+          in
+          {
+            allowedTCPPorts = [ portToOpen ];
+            allowedUDPPorts = [ portToOpen ];
+          };
       };
 
-      wantedBy = [ "multi-user.target" ];
+      systemd.services.dae =
+        let
+          daeBin = lib.getExe cfg.package;
+          TxChecksumIpGenericWorkaround = with lib;(getExe pkgs.writeShellApplication {
+            name = "disable-tx-checksum-ip-generic";
+            text = with pkgs; ''
+              iface=$(${iproute2}/bin/ip route | ${lib.getExe gawk} '/default/ {print $5}')
+              ${lib.getExe ethtool} -K "$iface" tx-checksum-ip-generic off
+            '';
+          });
+        in
+        {
+          wantedBy = [ "multi-user.target" ];
+          serviceConfig = {
+            ExecStartPre = [ "" "${daeBin} validate -c ${cfg.configFile}" ]
+              ++ (with lib; optional cfg.disableTxChecksumIpGeneric TxChecksumIpGenericWorkaround);
+            ExecStart = [ "" "${daeBin} run --disable-timestamp -c ${cfg.configFile}" ];
+            Environment = "DAE_LOCATION_ASSET=${cfg.assetsPath}";
+          };
+        };
+
+      assertions = [
+        {
+          assertion = lib.pathExists (toString (genAssetsDrv cfg.assets) + "/share/v2ray");
+          message = ''
+            Packages in `assets` has no preset paths included.
+            Please set `assetsPath` instead.
+          '';
+        }
+
+        {
+          assertion = !((config.services.dae.config != "global{}\nrouting{}\n")
+            && (config.services.dae.configFile != "/etc/dae/config.dae"));
+          message = ''
+            Option `config` and `configFile` could not be set
+            at the same time.
+          '';
+        }
+      ];
     };
-  };
 }
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
index de1ca0d2f206..4592a0c2f6b3 100644
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
@@ -11,7 +11,7 @@ in
     settings = mkOption {
       description = lib.mdDoc ''
         Attrset that is converted and passed as TOML config file.
-        For available params, see: <https://github.com/DNSCrypt/dnscrypt-proxy/blob/${pkgs.dnscrypt-proxy2.version}/dnscrypt-proxy/example-dnscrypt-proxy.toml>
+        For available params, see: <https://github.com/DNSCrypt/dnscrypt-proxy/blob/${pkgs.dnscrypt-proxy.version}/dnscrypt-proxy/example-dnscrypt-proxy.toml>
       '';
       example = literalExpression ''
         {
@@ -49,7 +49,7 @@ in
         passAsFile = [ "json" ];
       } ''
         ${if cfg.upstreamDefaults then ''
-          ${pkgs.remarshal}/bin/toml2json ${pkgs.dnscrypt-proxy2.src}/dnscrypt-proxy/example-dnscrypt-proxy.toml > example.json
+          ${pkgs.remarshal}/bin/toml2json ${pkgs.dnscrypt-proxy.src}/dnscrypt-proxy/example-dnscrypt-proxy.toml > example.json
           ${pkgs.jq}/bin/jq --slurp add example.json $jsonPath > config.json # merges the two
         '' else ''
           cp $jsonPath config.json
@@ -80,7 +80,7 @@ in
         AmbientCapabilities = "CAP_NET_BIND_SERVICE";
         CacheDirectory = "dnscrypt-proxy";
         DynamicUser = true;
-        ExecStart = "${pkgs.dnscrypt-proxy2}/bin/dnscrypt-proxy -config ${cfg.configFile}";
+        ExecStart = "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy -config ${cfg.configFile}";
         LockPersonality = true;
         LogsDirectory = "dnscrypt-proxy";
         MemoryDenyWriteExecute = true;
diff --git a/nixpkgs/nixos/modules/services/networking/jool.nix b/nixpkgs/nixos/modules/services/networking/jool.nix
index 3aafbe40967c..d2d2b0956e8a 100644
--- a/nixpkgs/nixos/modules/services/networking/jool.nix
+++ b/nixpkgs/nixos/modules/services/networking/jool.nix
@@ -16,7 +16,7 @@ let
     TemporaryFileSystem = [ "/" ];
     BindReadOnlyPaths = [
       builtins.storeDir
-      "/run/current-system/kernel-modules"
+      "/run/booted-system/kernel-modules"
     ];
 
     # Give capabilities to load the module and configure it
@@ -31,26 +31,96 @@ let
 
   configFormat = pkgs.formats.json {};
 
-  mkDefaultAttrs = lib.mapAttrs (n: v: lib.mkDefault v);
+  # Generate the config file of instance `name`
+  nat64Conf = name:
+    configFormat.generate "jool-nat64-${name}.conf"
+      (cfg.nat64.${name} // { instance = name; });
+  siitConf = name:
+    configFormat.generate "jool-siit-${name}.conf"
+      (cfg.siit.${name} // { instance = name; });
+
+  # NAT64 config type
+  nat64Options = lib.types.submodule {
+    # The format is plain JSON
+    freeformType = configFormat.type;
+    # Some options with a default value
+    options.framework = lib.mkOption {
+      type = lib.types.enum [ "netfilter" "iptables" ];
+      default = "netfilter";
+      description = lib.mdDoc ''
+        The framework to use for attaching Jool's translation to the exist
+        kernel packet processing rules. See the
+        [documentation](https://nicmx.github.io/Jool/en/intro-jool.html#design)
+        for the differences between the two options.
+      '';
+    };
+    options.global.pool6 = lib.mkOption {
+      type = lib.types.strMatching "[[:xdigit:]:]+/[[:digit:]]+"
+        // { description = "Network prefix in CIDR notation"; };
+      default = "64:ff9b::/96";
+      description = lib.mdDoc ''
+        The prefix used for embedding IPv4 into IPv6 addresses.
+        Defaults to the well-known NAT64 prefix, defined by
+        [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
+      '';
+    };
+  };
 
-  defaultNat64 = {
-    instance = "default";
-    framework = "netfilter";
-    global.pool6 = "64:ff9b::/96";
+  # SIIT config type
+  siitOptions = lib.types.submodule {
+    # The format is, again, plain JSON
+    freeformType = configFormat.type;
+    # Some options with a default value
+    options = { inherit (nat64Options.getSubOptions []) framework; };
+  };
+
+  makeNat64Unit = name: opts: {
+    "jool-nat64-${name}" = {
+      description = "Jool, NAT64 setup of instance ${name}";
+      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool";
+        ExecStart    = "${jool-cli}/bin/jool file handle ${nat64Conf name}";
+        ExecStop     = "${jool-cli}/bin/jool -f ${nat64Conf name} instance remove";
+      } // hardening;
+    };
   };
-  defaultSiit = {
-    instance = "default";
-    framework = "netfilter";
+
+  makeSiitUnit = name: opts: {
+    "jool-siit-${name}" = {
+      description = "Jool, SIIT setup of instance ${name}";
+      documentation = [ "https://nicmx.github.io/Jool/en/documentation.html" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStartPre = "${pkgs.kmod}/bin/modprobe jool_siit";
+        ExecStart    = "${jool-cli}/bin/jool_siit file handle ${siitConf name}";
+        ExecStop     = "${jool-cli}/bin/jool_siit -f ${siitConf name} instance remove";
+      } // hardening;
+    };
   };
 
-  nat64Conf = configFormat.generate "jool-nat64.conf" cfg.nat64.config;
-  siitConf  = configFormat.generate "jool-siit.conf" cfg.siit.config;
+  checkNat64 = name: _: ''
+    printf 'Validating Jool configuration for NAT64 instance "${name}"... '
+    jool file check ${nat64Conf name}
+    printf 'Ok.\n'; touch "$out"
+  '';
+
+  checkSiit = name: _: ''
+    printf 'Validating Jool configuration for SIIT instance "${name}"... '
+    jool_siit file check ${siitConf name}
+    printf 'Ok.\n'; touch "$out"
+  '';
 
 in
 
 {
-  ###### interface
-
   options = {
     networking.jool.enable = lib.mkOption {
       type = lib.types.bool;
@@ -64,157 +134,146 @@ in
         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.
+
+        Enabling this option will install the Jool kernel module and the
+        command line tools for controlling it.
       '';
     };
 
-    networking.jool.nat64.enable = lib.mkEnableOption (lib.mdDoc "a NAT64 instance of Jool.");
-    networking.jool.nat64.config = lib.mkOption {
-      type = configFormat.type;
-      default = defaultNat64;
+    networking.jool.nat64 = lib.mkOption {
+      type = lib.types.attrsOf nat64Options;
+      default = { };
       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"; }
-          ];
+          default = {
+            # 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 = [
+              # Port ranges 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.
+        Definitions of NAT64 instances of Jool.
+        See the
+        [documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
+        the available options. Also check out the
+        [tutorial](https://nicmx.github.io/Jool/en/run-nat64.html) for an
+        introduction to NAT64 and how to troubleshoot the setup.
+
+        The attribute name defines the name of the instance, with the main one
+        being `default`: this can be accessed from the command line without
+        specifying the name with `-i`.
 
         ::: {.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.
+        Instances created imperatively from the command line will not interfere
+        with the NixOS instances, 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`.
+        Changes to an instance performed via `jool -i <name>` are applied
+        correctly but will be lost after restarting the respective
+        `jool-nat64-<name>.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;
+    networking.jool.siit = lib.mkOption {
+      type = lib.types.attrsOf siitOptions;
+      default = { };
       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" }
-          ]
+          default = {
+            # Maps any IPv4 address x.y.z.t to 2001:db8::x.y.z.t and v.v.
+            global.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.
+        Definitions of SIIT instances of Jool.
+        See the
+        [documentation](https://nicmx.github.io/Jool/en/config-atomic.html) for
+        the available options. Also check out the
+        [tutorial](https://nicmx.github.io/Jool/en/run-vanilla.html) for an
+        introduction to SIIT and how to troubleshoot the setup.
+
+        The attribute name defines the name of the instance, with the main one
+        being `default`: this can be accessed from the command line without
+        specifying the name with `-i`.
 
         ::: {.note}
-        Existing or more instances created manually will not interfere with the
-        NixOS instance, provided the respective `EAMT` address mappings are not
-        overlapping.
+        Instances created imperatively from the command line will not interfere
+        with the NixOS instances, provided the respective EAMT addresses and
+        port ranges 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`.
+        Changes to an instance performed via `jool -i <name>` are applied
+        correctly but will be lost after restarting the respective
+        `jool-siit-<name>.service`.
         :::
       '';
     };
 
   };
 
-  ###### implementation
-
   config = lib.mkIf cfg.enable {
-    environment.systemPackages = [ jool-cli ];
+    # Install kernel module and cli tools
     boot.extraModulePackages = [ jool ];
+    environment.systemPackages = [ jool-cli ];
 
-    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;
+    # Install services for each instance
+    systemd.services = lib.mkMerge
+      (lib.mapAttrsToList makeNat64Unit cfg.nat64 ++
+       lib.mapAttrsToList makeSiitUnit cfg.siit);
 
+    # Check the configuration of each instance
+    system.checks = lib.optional (cfg.nat64 != {} || cfg.siit != {})
+      (pkgs.runCommand "jool-validated"
+        {
+          nativeBuildInputs = with pkgs.buildPackages; [ jool-cli ];
+          preferLocalBuild = true;
+        }
+        (lib.concatStrings
+          (lib.mapAttrsToList checkNat64 cfg.nat64 ++
+           lib.mapAttrsToList checkSiit cfg.siit)));
   };
 
   meta.maintainers = with lib.maintainers; [ rnhmjoj ];
diff --git a/nixpkgs/nixos/modules/services/networking/nftables.nix b/nixpkgs/nixos/modules/services/networking/nftables.nix
index 0e4cd6fa1503..47159ade328c 100644
--- a/nixpkgs/nixos/modules/services/networking/nftables.nix
+++ b/nixpkgs/nixos/modules/services/networking/nftables.nix
@@ -70,6 +70,26 @@ in
       '';
     };
 
+    networking.nftables.checkRulesetRedirects = mkOption {
+      type = types.addCheck (types.attrsOf types.path) (attrs: all types.path.check (attrNames attrs));
+      default = {
+        "/etc/hosts" = config.environment.etc.hosts.source;
+        "/etc/protocols" = config.environment.etc.protocols.source;
+        "/etc/services" = config.environment.etc.services.source;
+      };
+      defaultText = literalExpression ''
+        {
+          "/etc/hosts" = config.environment.etc.hosts.source;
+          "/etc/protocols" = config.environment.etc.protocols.source;
+          "/etc/services" = config.environment.etc.services.source;
+        }
+      '';
+      description = mdDoc ''
+        Set of paths that should be intercepted and rewritten while checking the ruleset
+        using `pkgs.buildPackages.libredirect`.
+      '';
+    };
+
     networking.nftables.preCheckRuleset = mkOption {
       type = types.lines;
       default = "";
@@ -282,7 +302,7 @@ in
             cp $out ruleset.conf
             sed 's|include "${deletionsScriptVar}"||' -i ruleset.conf
             ${cfg.preCheckRuleset}
-            export NIX_REDIRECTS=/etc/protocols=${pkgs.buildPackages.iana-etc}/etc/protocols:/etc/services=${pkgs.buildPackages.iana-etc}/etc/services
+            export NIX_REDIRECTS=${escapeShellArg (concatStringsSep ":" (mapAttrsToList (n: v: "${n}=${v}") cfg.checkRulesetRedirects))}
             LD_PRELOAD="${pkgs.buildPackages.libredirect}/lib/libredirect.so ${pkgs.buildPackages.lklWithFirewall.lib}/lib/liblkl-hijack.so" \
               ${pkgs.buildPackages.nftables}/bin/nft --check --file ruleset.conf
           '';
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.nix b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
index b0d3c44cea81..4d1084e295ff 100644
--- a/nixpkgs/nixos/modules/services/web-apps/grocy.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
@@ -115,9 +115,9 @@ in {
       user = "grocy";
       group = "nginx";
 
-      # 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;
+      # PHP 8.1 and 8.2 are the only version which are supported/tested by upstream:
+      # https://github.com/grocy/grocy/blob/v4.0.2/README.md#platform-support
+      phpPackage = pkgs.php82;
 
       inherit (cfg.phpfpm) settings;
 
@@ -130,6 +130,16 @@ in {
       };
     };
 
+    # After an update of grocy, the viewcache needs to be deleted. Otherwise grocy will not work
+    # https://github.com/grocy/grocy#how-to-update
+    systemd.services.grocy-setup = {
+      wantedBy = [ "multi-user.target" ];
+      before = [ "phpfpm-grocy.service" ];
+      script = ''
+        rm -rf ${cfg.dataDir}/viewcache/*
+      '';
+    };
+
     services.nginx = {
       enable = true;
       virtualHosts."${cfg.hostName}" = mkMerge [
diff --git a/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix b/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix
new file mode 100644
index 000000000000..4e796e2bc80c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/mobilizon.nix
@@ -0,0 +1,442 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mobilizon;
+
+  user = "mobilizon";
+  group = "mobilizon";
+
+  settingsFormat = pkgs.formats.elixirConf { elixir = pkgs.elixir_1_14; };
+
+  configFile = settingsFormat.generate "mobilizon-config.exs" cfg.settings;
+
+  # Make a package containing launchers with the correct envirenment, instead of
+  # setting it with systemd services, so that the user can also use them without
+  # troubles
+  launchers = pkgs.stdenv.mkDerivation rec {
+    pname = "${cfg.package.pname}-launchers";
+    inherit (cfg.package) version;
+
+    src = cfg.package;
+
+    nativeBuildInputs = with pkgs; [ makeWrapper ];
+
+    dontBuild = true;
+
+    installPhase = ''
+      mkdir -p $out/bin
+
+      makeWrapper \
+        $src/bin/mobilizon \
+        $out/bin/mobilizon \
+        --run '. ${secretEnvFile}' \
+        --set MOBILIZON_CONFIG_PATH "${configFile}" \
+        --set-default RELEASE_TMP "/tmp"
+
+      makeWrapper \
+        $src/bin/mobilizon_ctl \
+        $out/bin/mobilizon_ctl \
+        --run '. ${secretEnvFile}' \
+        --set MOBILIZON_CONFIG_PATH "${configFile}" \
+        --set-default RELEASE_TMP "/tmp"
+    '';
+  };
+
+  repoSettings = cfg.settings.":mobilizon"."Mobilizon.Storage.Repo";
+  instanceSettings = cfg.settings.":mobilizon".":instance";
+
+  isLocalPostgres = repoSettings.socket_dir != null;
+
+  dbUser = if repoSettings.username != null then repoSettings.username else "mobilizon";
+
+  postgresql = config.services.postgresql.package;
+  postgresqlSocketDir = "/var/run/postgresql";
+
+  secretEnvFile = "/var/lib/mobilizon/secret-env.sh";
+in
+{
+  options = {
+    services.mobilizon = {
+      enable = mkEnableOption
+        "Mobilizon federated organization and mobilization platform";
+
+      nginx.enable = lib.mkOption {
+        type = lib.types.bool;
+        default = true;
+        description = ''
+          Whether an <literal>nginx</literal> virtual host should be
+          set up to serve Mobilizon.
+        '';
+      };
+
+      package = mkPackageOptionMD pkgs "mobilizon" { };
+
+      settings = mkOption {
+        type =
+          let
+            elixirTypes = settingsFormat.lib.types;
+          in
+          types.submodule {
+            freeformType = settingsFormat.type;
+
+            options = {
+              ":mobilizon" = {
+
+                "Mobilizon.Web.Endpoint" = {
+                  url.host = mkOption {
+                    type = elixirTypes.str;
+                    defaultText = literalExpression ''
+                      ''${settings.":mobilizon".":instance".hostname}
+                    '';
+                    description = ''
+                      Your instance's hostname for generating URLs throughout the app
+                    '';
+                  };
+
+                  http = {
+                    port = mkOption {
+                      type = elixirTypes.port;
+                      default = 4000;
+                      description = ''
+                        The port to run the server
+                      '';
+                    };
+                    ip = mkOption {
+                      type = elixirTypes.tuple;
+                      default = settingsFormat.lib.mkTuple [ 0 0 0 0 0 0 0 1 ];
+                      description = ''
+                        The IP address to listen on. Defaults to [::1] notated as a byte tuple.
+                      '';
+                    };
+                  };
+
+                  has_reverse_proxy = mkOption {
+                    type = elixirTypes.bool;
+                    default = true;
+                    description = ''
+                      Whether you use a reverse proxy
+                    '';
+                  };
+                };
+
+                ":instance" = {
+                  name = mkOption {
+                    type = elixirTypes.str;
+                    description = ''
+                      The fallback instance name if not configured into the admin UI
+                    '';
+                  };
+
+                  hostname = mkOption {
+                    type = elixirTypes.str;
+                    description = ''
+                      Your instance's hostname
+                    '';
+                  };
+
+                  email_from = mkOption {
+                    type = elixirTypes.str;
+                    defaultText = literalExpression ''
+                      noreply@''${settings.":mobilizon".":instance".hostname}
+                    '';
+                    description = ''
+                      The email for the From: header in emails
+                    '';
+                  };
+
+                  email_reply_to = mkOption {
+                    type = elixirTypes.str;
+                    defaultText = literalExpression ''
+                      ''${email_from}
+                    '';
+                    description = ''
+                      The email for the Reply-To: header in emails
+                    '';
+                  };
+                };
+
+                "Mobilizon.Storage.Repo" = {
+                  socket_dir = mkOption {
+                    type = types.nullOr elixirTypes.str;
+                    default = postgresqlSocketDir;
+                    description = ''
+                      Path to the postgres socket directory.
+
+                      Set this to null if you want to connect to a remote database.
+
+                      If non-null, the local PostgreSQL server will be configured with
+                      the configured database, permissions, and required extensions.
+
+                      If connecting to a remote database, please follow the
+                      instructions on how to setup your database:
+                      <link xlink:href="https://docs.joinmobilizon.org/administration/install/release/#database-setup"/>
+                    '';
+                  };
+
+                  username = mkOption {
+                    type = types.nullOr elixirTypes.str;
+                    default = user;
+                    description = ''
+                      User used to connect to the database
+                    '';
+                  };
+
+                  database = mkOption {
+                    type = types.nullOr elixirTypes.str;
+                    default = "mobilizon_prod";
+                    description = ''
+                      Name of the database
+                    '';
+                  };
+                };
+              };
+            };
+          };
+        default = { };
+
+        description = ''
+          Mobilizon Elixir documentation, see
+          <link xlink:href="https://docs.joinmobilizon.org/administration/configure/reference/"/>
+          for supported values.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    assertions = [
+      {
+        assertion = cfg.nginx.enable -> (cfg.settings.":mobilizon"."Mobilizon.Web.Endpoint".http.ip == settingsFormat.lib.mkTuple [ 0 0 0 0 0 0 0 1 ]);
+        message = "Setting the IP mobilizon listens on is only possible when the nginx config is not used, as it is hardcoded there.";
+      }
+    ];
+
+    services.mobilizon.settings = {
+      ":mobilizon" = {
+        "Mobilizon.Web.Endpoint" = {
+          server = true;
+          url.host = mkDefault instanceSettings.hostname;
+          secret_key_base =
+            settingsFormat.lib.mkGetEnv { envVariable = "MOBILIZON_INSTANCE_SECRET"; };
+        };
+
+        "Mobilizon.Web.Auth.Guardian".secret_key =
+          settingsFormat.lib.mkGetEnv { envVariable = "MOBILIZON_AUTH_SECRET"; };
+
+        ":instance" = {
+          registrations_open = mkDefault false;
+          demo = mkDefault false;
+          email_from = mkDefault "noreply@${instanceSettings.hostname}";
+          email_reply_to = mkDefault instanceSettings.email_from;
+        };
+
+        "Mobilizon.Storage.Repo" = {
+          # Forced by upstream since it uses PostgreSQL-specific extensions
+          adapter = settingsFormat.lib.mkAtom "Ecto.Adapters.Postgres";
+          pool_size = mkDefault 10;
+        };
+      };
+
+      ":tzdata".":data_dir" = "/var/lib/mobilizon/tzdata/";
+    };
+
+    # This somewhat follows upstream's systemd service here:
+    # https://framagit.org/framasoft/mobilizon/-/blob/master/support/systemd/mobilizon.service
+    systemd.services.mobilizon = {
+      description = "Mobilizon federated organization and mobilization platform";
+
+      wantedBy = [ "multi-user.target" ];
+
+      path = with pkgs; [
+        gawk
+        imagemagick
+        libwebp
+        file
+
+        # Optional:
+        gifsicle
+        jpegoptim
+        optipng
+        pngquant
+      ];
+
+      serviceConfig = {
+        ExecStartPre = "${launchers}/bin/mobilizon_ctl migrate";
+        ExecStart = "${launchers}/bin/mobilizon start";
+        ExecStop = "${launchers}/bin/mobilizon stop";
+
+        User = user;
+        Group = group;
+
+        StateDirectory = "mobilizon";
+
+        Restart = "on-failure";
+
+        PrivateTmp = true;
+        ProtectSystem = "full";
+        NoNewPrivileges = true;
+
+        ReadWritePaths = mkIf isLocalPostgres postgresqlSocketDir;
+      };
+    };
+
+    # Create the needed secrets before running Mobilizon, so that they are not
+    # in the nix store
+    #
+    # Since some of these tasks are quite common for Elixir projects (COOKIE for
+    # every BEAM project, Phoenix and Guardian are also quite common), this
+    # service could be abstracted in the future, and used by other Elixir
+    # projects.
+    systemd.services.mobilizon-setup-secrets = {
+      description = "Mobilizon setup secrets";
+      before = [ "mobilizon.service" ];
+      wantedBy = [ "mobilizon.service" ];
+
+      script =
+        let
+          # Taken from here:
+          # https://framagit.org/framasoft/mobilizon/-/blob/1.0.7/lib/mix/tasks/mobilizon/instance.ex#L132-133
+          genSecret =
+            "IO.puts(:crypto.strong_rand_bytes(64)" +
+            "|> Base.encode64()" +
+            "|> binary_part(0, 64))";
+
+          # Taken from here:
+          # https://github.com/elixir-lang/elixir/blob/v1.11.3/lib/mix/lib/mix/release.ex#L499
+          genCookie = "IO.puts(Base.encode32(:crypto.strong_rand_bytes(32)))";
+
+          evalElixir = str: ''
+            ${pkgs.elixir_1_14}/bin/elixir --eval '${str}'
+          '';
+        in
+        ''
+          set -euxo pipefail
+
+          if [ ! -f "${secretEnvFile}" ]; then
+            install -m 600 /dev/null "${secretEnvFile}"
+            cat > "${secretEnvFile}" <<EOF
+          # This file was automatically generated by mobilizon-setup-secrets.service
+          export MOBILIZON_AUTH_SECRET='$(${evalElixir genSecret})'
+          export MOBILIZON_INSTANCE_SECRET='$(${evalElixir genSecret})'
+          export RELEASE_COOKIE='$(${evalElixir genCookie})'
+          EOF
+          fi
+        '';
+
+      serviceConfig = {
+        Type = "oneshot";
+        User = user;
+        Group = group;
+        StateDirectory = "mobilizon";
+      };
+    };
+
+    # Add the required PostgreSQL extensions to the local PostgreSQL server,
+    # if local PostgreSQL is configured.
+    systemd.services.mobilizon-postgresql = mkIf isLocalPostgres {
+      description = "Mobilizon PostgreSQL setup";
+
+      after = [ "postgresql.service" ];
+      before = [ "mobilizon.service" "mobilizon-setup-secrets.service" ];
+      wantedBy = [ "mobilizon.service" ];
+
+      path = [ postgresql ];
+
+      # Taken from here:
+      # https://framagit.org/framasoft/mobilizon/-/blob/1.1.0/priv/templates/setup_db.eex
+      script =
+        ''
+          psql "${repoSettings.database}" -c "\
+            CREATE EXTENSION IF NOT EXISTS postgis; \
+            CREATE EXTENSION IF NOT EXISTS pg_trgm; \
+            CREATE EXTENSION IF NOT EXISTS unaccent;"
+        '';
+
+      serviceConfig = {
+        Type = "oneshot";
+        User = config.services.postgresql.superUser;
+      };
+    };
+
+    systemd.tmpfiles.rules = [
+      "d /var/lib/mobilizon/uploads/exports/csv 700 mobilizon mobilizon - -"
+      "Z /var/lib/mobilizon 700 mobilizon mobilizon - -"
+    ];
+
+    services.postgresql = mkIf isLocalPostgres {
+      enable = true;
+      ensureDatabases = [ repoSettings.database ];
+      ensureUsers = [
+        {
+          name = dbUser;
+          ensurePermissions = {
+            "DATABASE \"${repoSettings.database}\"" = "ALL PRIVILEGES";
+          };
+        }
+      ];
+      extraPlugins = with postgresql.pkgs; [ postgis ];
+    };
+
+    # Nginx config taken from support/nginx/mobilizon-release.conf
+    services.nginx =
+      let
+        inherit (cfg.settings.":mobilizon".":instance") hostname;
+        proxyPass = "http://[::1]:"
+          + toString cfg.settings.":mobilizon"."Mobilizon.Web.Endpoint".http.port;
+      in
+      lib.mkIf cfg.nginx.enable {
+        enable = true;
+        virtualHosts."${hostname}" = {
+          enableACME = lib.mkDefault true;
+          forceSSL = lib.mkDefault true;
+          extraConfig = ''
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection "upgrade";
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+          '';
+          locations."/" = {
+            inherit proxyPass;
+          };
+          locations."~ ^/(js|css|img)" = {
+            root = "${cfg.package}/lib/mobilizon-${cfg.package.version}/priv/static";
+            extraConfig = ''
+              etag off;
+              access_log off;
+              add_header Cache-Control "public, max-age=31536000, immutable";
+            '';
+          };
+          locations."~ ^/(media|proxy)" = {
+            inherit proxyPass;
+            extraConfig = ''
+              etag off;
+              access_log off;
+              add_header Cache-Control "public, max-age=31536000, immutable";
+            '';
+          };
+        };
+      };
+
+    users.users.${user} = {
+      description = "Mobilizon daemon user";
+      group = group;
+      isSystemUser = true;
+    };
+
+    users.groups.${group} = { };
+
+    # So that we have the `mobilizon` and `mobilizon_ctl` commands.
+    # The `mobilizon remote` command is useful for dropping a shell into the
+    # running Mobilizon instance, and `mobilizon_ctl` is used for common
+    # management tasks (e.g. adding users).
+    environment.systemPackages = [ launchers ];
+  };
+
+  meta.maintainers = with lib.maintainers; [ minijackson erictapen ];
+}
diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
index fccc31b5116c..7a7fb4061eea 100644
--- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
@@ -578,11 +578,13 @@ in
           };
         });
         default = [];
-        example = literalExpression ''[
-          { addr = "10.0.0.12"; proxyProtocol = true; ssl = true; }
-          { addr = "0.0.0.0"; }
-          { addr = "[::0]"; }
-        ]'';
+        example = literalExpression ''
+          [
+            { addr = "10.0.0.12"; proxyProtocol = true; ssl = true; }
+            { addr = "0.0.0.0"; }
+            { addr = "[::0]"; }
+          ]
+        '';
         description = lib.mdDoc ''
           If vhosts do not specify listen, use these addresses by default.
           This option takes precedence over {option}`defaultListenAddresses` and
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
index bee627ec76c0..a4f8bd5051ec 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -134,6 +134,7 @@ in {
         # Update user directories.
         xdg-user-dirs
       ]
+      ++ lib.optional config.networking.networkmanager.enable pkgs.networkmanagerapplet
       ++ (utils.removePackagesByName [
           cinnamon.nemo
           mate.eom
@@ -192,7 +193,7 @@ in {
     # Required by Budgie Panel plugins and/or Budgie Control Center panels.
     networking.networkmanager.enable = mkDefault true; # for BCC's Network panel.
     programs.nm-applet.enable = config.networking.networkmanager.enable; # Budgie has no Network applet.
-    programs.nm-applet.indicator = false; # Budgie doesn't support AppIndicators.
+    programs.nm-applet.indicator = true; # Budgie uses AppIndicators.
 
     hardware.bluetooth.enable = mkDefault true; # for Budgie's Status Indicator and BCC's Bluetooth panel.
     hardware.pulseaudio.enable = mkDefault true; # for Budgie's Status Indicator and BCC's Sound panel.
diff --git a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
index f9a2084ea9e8..c0af29e3b990 100755
--- a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
@@ -104,7 +104,10 @@ fi
 
 
 # Required by the activation script
-install -m 0755 -d /etc /etc/nixos
+install -m 0755 -d /etc
+if [ -d "/etc/nixos" ]; then
+    install -m 0755 -d /etc/nixos
+fi
 install -m 01777 -d /tmp
 
 
diff --git a/nixpkgs/nixos/modules/system/boot/systemd/initrd.nix b/nixpkgs/nixos/modules/system/boot/systemd/initrd.nix
index 3f40a5b2dfa0..5d9fca7a605e 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd/initrd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd/initrd.nix
@@ -333,6 +333,14 @@ in {
       visible = "shallow";
       description = lib.mdDoc "Definition of slice configurations.";
     };
+
+    enableTpm2 = mkOption {
+      default = true;
+      type = types.bool;
+      description = lib.mdDoc ''
+        Whether to enable TPM2 support in the initrd.
+      '';
+    };
   };
 
   config = mkIf (config.boot.initrd.enable && cfg.enable) {
@@ -342,8 +350,8 @@ in {
       # systemd needs this for some features
       "autofs4"
       # systemd-cryptenroll
-      "tpm-tis"
-    ] ++ lib.optional (pkgs.stdenv.hostPlatform.system != "riscv64-linux") "tpm-crb";
+    ] ++ lib.optional cfg.enableTpm2 "tpm-tis"
+    ++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb";
 
     boot.initrd.systemd = {
       initrdBin = [pkgs.bash pkgs.coreutils cfg.package.kmod cfg.package] ++ config.system.fsPackages;
@@ -421,11 +429,11 @@ in {
 
         # so NSS can look up usernames
         "${pkgs.glibc}/lib/libnss_files.so.2"
-      ] ++ optionals cfg.package.withCryptsetup [
+      ] ++ optionals (cfg.package.withCryptsetup && cfg.enableTpm2) [
         # tpm2 support
         "${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
         pkgs.tpm2-tss
-
+      ] ++ optionals cfg.package.withCryptsetup [
         # fido2 support
         "${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"
         "${pkgs.libfido2}/lib/libfido2.so.1"
diff --git a/nixpkgs/nixos/modules/system/boot/systemd/user.nix b/nixpkgs/nixos/modules/system/boot/systemd/user.nix
index 1b6398d2f929..64dc19633eca 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd/user.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd/user.nix
@@ -230,5 +230,9 @@ in {
           });
         })
         cfg.tmpfiles.users;
+
+    system.userActivationScripts.tmpfiles = ''
+      ${config.systemd.package}/bin/systemd-tmpfiles --user --create --remove
+    '';
   };
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/anbox.nix b/nixpkgs/nixos/modules/virtualisation/anbox.nix
index c7e9e23c4c92..523d9a9576ef 100644
--- a/nixpkgs/nixos/modules/virtualisation/anbox.nix
+++ b/nixpkgs/nixos/modules/virtualisation/anbox.nix
@@ -5,7 +5,7 @@ with lib;
 let
 
   cfg = config.virtualisation.anbox;
-  kernelPackages = config.boot.kernelPackages;
+
   addrOpts = v: addr: pref: name: {
     address = mkOption {
       default = addr;
@@ -25,6 +25,28 @@ let
     };
   };
 
+  finalImage = if cfg.imageModifications == "" then cfg.image else ( pkgs.callPackage (
+    { runCommandNoCC, squashfsTools }:
+
+    runCommandNoCC "${cfg.image.name}-modified.img" {
+      nativeBuildInputs = [
+        squashfsTools
+      ];
+    } ''
+      echo "-> Extracting Anbox root image..."
+      unsquashfs -dest rootfs ${cfg.image}
+
+      echo "-> Modifying Anbox root image..."
+      (
+      cd rootfs
+      ${cfg.imageModifications}
+      )
+
+      echo "-> Packing modified Anbox root image..."
+      mksquashfs rootfs $out -comp xz -no-xattrs -all-root
+    ''
+  ) { });
+
 in
 
 {
@@ -42,6 +64,18 @@ in
       '';
     };
 
+    imageModifications = mkOption {
+      default = "";
+      type = types.lines;
+      description = lib.mdDoc ''
+        Commands to edit the image filesystem.
+
+        This can be used to e.g. bundle a privileged F-Droid.
+
+        Commands are ran with PWD being at the root of the filesystem.
+      '';
+    };
+
     extraInit = mkOption {
       type = types.lines;
       default = "";
@@ -67,16 +101,19 @@ in
   config = mkIf cfg.enable {
 
     assertions = singleton {
-      assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18";
-      message = "Anbox needs user namespace support to work properly";
+      assertion = with config.boot.kernelPackages; kernelAtLeast "5.5" && kernelOlder "5.18";
+      message = "Anbox needs a kernel with binder and ashmem support";
     };
 
     environment.systemPackages = with pkgs; [ anbox ];
 
-    services.udev.extraRules = ''
-      KERNEL=="ashmem", NAME="%k", MODE="0666"
-      KERNEL=="binder*", NAME="%k", MODE="0666"
-    '';
+    systemd.mounts = singleton {
+      requiredBy = [ "anbox-container-manager.service" ];
+      description = "Anbox Binder File System";
+      what = "binder";
+      where = "/dev/binderfs";
+      type = "binder";
+    };
 
     virtualisation.lxc.enable = true;
     networking.bridges.anbox0.interfaces = [];
@@ -87,6 +124,9 @@ in
       internalInterfaces = [ "anbox0" ];
     };
 
+    # Ensures NetworkManager doesn't touch anbox0
+    networking.networkmanager.unmanaged = [ "anbox0" ];
+
     systemd.services.anbox-container-manager = let
       anboxloc = "/var/lib/anbox";
     in {
@@ -121,12 +161,13 @@ in
         ExecStart = ''
           ${pkgs.anbox}/bin/anbox container-manager \
             --data-path=${anboxloc} \
-            --android-image=${cfg.image} \
+            --android-image=${finalImage} \
             --container-network-address=${cfg.ipv4.container.address} \
             --container-network-gateway=${cfg.ipv4.gateway.address} \
             --container-network-dns-servers=${cfg.ipv4.dns} \
             --use-rootfs-overlay \
-            --privileged
+            --privileged \
+            --daemon
         '';
       };
     };
diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
index 55b285b69147..9402d3bf37d0 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxc-container.nix
@@ -1,96 +1,16 @@
 { lib, config, pkgs, ... }:
 
-with lib;
-
 let
-  templateSubmodule = { ... }: {
-    options = {
-      enable = mkEnableOption (lib.mdDoc "this template");
-
-      target = mkOption {
-        description = lib.mdDoc "Path in the container";
-        type = types.path;
-      };
-      template = mkOption {
-        description = lib.mdDoc ".tpl file for rendering the target";
-        type = types.path;
-      };
-      when = mkOption {
-        description = lib.mdDoc "Events which trigger a rewrite (create, copy)";
-        type = types.listOf (types.str);
-      };
-      properties = mkOption {
-        description = lib.mdDoc "Additional properties";
-        type = types.attrs;
-        default = {};
-      };
-    };
-  };
-
-  toYAML = name: data: pkgs.writeText name (generators.toYAML {} data);
-
   cfg = config.virtualisation.lxc;
-  templates = if cfg.templates != {} then let
-    list = mapAttrsToList (name: value: { inherit name; } // value)
-      (filterAttrs (name: value: value.enable) cfg.templates);
-  in
-    {
-      files = map (tpl: {
-        source = tpl.template;
-        target = "/templates/${tpl.name}.tpl";
-      }) list;
-      properties = listToAttrs (map (tpl: nameValuePair tpl.target {
-        when = tpl.when;
-        template = "${tpl.name}.tpl";
-        properties = tpl.properties;
-      }) list);
-    }
-  else { files = []; properties = {}; };
-
-in
-{
+in {
   imports = [
-    ../installer/cd-dvd/channel.nix
-    ../profiles/clone-config.nix
-    ../profiles/minimal.nix
+    ./lxc-instance-common.nix
   ];
 
   options = {
     virtualisation.lxc = {
-      templates = mkOption {
-        description = lib.mdDoc "Templates for LXD";
-        type = types.attrsOf (types.submodule (templateSubmodule));
-        default = {};
-        example = literalExpression ''
-          {
-            # create /etc/hostname on container creation. also requires networking.hostName = "" to be set
-            "hostname" = {
-              enable = true;
-              target = "/etc/hostname";
-              template = builtins.toFile "hostname.tpl" "{{ container.name }}";
-              when = [ "create" ];
-            };
-            # create /etc/nixos/hostname.nix with a configuration for keeping the hostname applied
-            "hostname-nix" = {
-              enable = true;
-              target = "/etc/nixos/hostname.nix";
-              template = builtins.toFile "hostname-nix.tpl" "{ ... }: { networking.hostName = \"{{ container.name }}\"; }";
-              # copy keeps the file updated when the container is changed
-              when = [ "create" "copy" ];
-            };
-            # copy allow the user to specify a custom configuration.nix
-            "configuration-nix" = {
-              enable = true;
-              target = "/etc/nixos/configuration.nix";
-              template = builtins.toFile "configuration-nix" "{{ config_get(\"user.user-data\", properties.default) }}";
-              when = [ "create" ];
-            };
-          };
-        '';
-      };
-
-      privilegedContainer = mkOption {
-        type = types.bool;
+      privilegedContainer = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = lib.mdDoc ''
           Whether this LXC container will be running as a privileged container or not. If set to `true` then
@@ -116,24 +36,6 @@ in
         ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
       '';
 
-    system.build.metadata = pkgs.callPackage ../../lib/make-system-tarball.nix {
-      contents = [
-        {
-          source = toYAML "metadata.yaml" {
-            architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.system)) 0;
-            creation_date = 1;
-            properties = {
-              description = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
-              os = "${config.system.nixos.distroId}";
-              release = "${config.system.nixos.codeName}";
-            };
-            templates = templates.properties;
-          };
-          target = "/metadata.yaml";
-        }
-      ] ++ templates.files;
-    };
-
     # TODO: build rootfs as squashfs for faster unpack
     system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
       extraArgs = "--owner=0";
@@ -180,7 +82,7 @@ in
           ProtectKernelTunables=no
           NoNewPrivileges=no
           LoadCredential=
-        '' + optionalString cfg.privilegedContainer ''
+        '' + lib.optionalString cfg.privilegedContainer ''
           # Additional settings for privileged containers
           ProtectHome=no
           ProtectSystem=no
@@ -193,28 +95,8 @@ in
       })
     ];
 
-    # Allow the user to login as root without password.
-    users.users.root.initialHashedPassword = mkOverride 150 "";
-
-    system.activationScripts.installInitScript = mkForce ''
+    system.activationScripts.installInitScript = lib.mkForce ''
       ln -fs $systemConfig/init /sbin/init
     '';
-
-    # Some more help text.
-    services.getty.helpLine =
-      ''
-
-        Log in as "root" with an empty password.
-      '';
-
-    # Containers should be light-weight, so start sshd on demand.
-    services.openssh.enable = mkDefault true;
-    services.openssh.startWhenNeeded = mkDefault true;
-
-    # As this is intended as a standalone image, undo some of the minimal profile stuff
-    environment.noXlibs = false;
-    documentation.enable = true;
-    documentation.nixos.enable = true;
-    services.logrotate.enable = true;
   };
 }
diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-image-metadata.nix b/nixpkgs/nixos/modules/virtualisation/lxc-image-metadata.nix
new file mode 100644
index 000000000000..2c0568b4c468
--- /dev/null
+++ b/nixpkgs/nixos/modules/virtualisation/lxc-image-metadata.nix
@@ -0,0 +1,104 @@
+{ lib, config, pkgs, ... }:
+
+let
+  templateSubmodule = {...}: {
+    options = {
+      enable = lib.mkEnableOption "this template";
+
+      target = lib.mkOption {
+        description = "Path in the container";
+        type = lib.types.path;
+      };
+      template = lib.mkOption {
+        description = ".tpl file for rendering the target";
+        type = lib.types.path;
+      };
+      when = lib.mkOption {
+        description = "Events which trigger a rewrite (create, copy)";
+        type = lib.types.listOf (lib.types.str);
+      };
+      properties = lib.mkOption {
+        description = "Additional properties";
+        type = lib.types.attrs;
+        default = {};
+      };
+    };
+  };
+
+  toYAML = name: data: pkgs.writeText name (lib.generators.toYAML {} data);
+
+  cfg = config.virtualisation.lxc;
+  templates = if cfg.templates != {} then let
+    list = lib.mapAttrsToList (name: value: { inherit name; } // value)
+      (lib.filterAttrs (name: value: value.enable) cfg.templates);
+  in
+    {
+      files = map (tpl: {
+        source = tpl.template;
+        target = "/templates/${tpl.name}.tpl";
+      }) list;
+      properties = lib.listToAttrs (map (tpl: lib.nameValuePair tpl.target {
+        when = tpl.when;
+        template = "${tpl.name}.tpl";
+        properties = tpl.properties;
+      }) list);
+    }
+  else { files = []; properties = {}; };
+
+in {
+  options = {
+    virtualisation.lxc = {
+      templates = lib.mkOption {
+        description = "Templates for LXD";
+        type = lib.types.attrsOf (lib.types.submodule templateSubmodule);
+        default = {};
+        example = lib.literalExpression ''
+          {
+            # create /etc/hostname on container creation
+            "hostname" = {
+              enable = true;
+              target = "/etc/hostname";
+              template = builtins.writeFile "hostname.tpl" "{{ container.name }}";
+              when = [ "create" ];
+            };
+            # create /etc/nixos/hostname.nix with a configuration for keeping the hostname applied
+            "hostname-nix" = {
+              enable = true;
+              target = "/etc/nixos/hostname.nix";
+              template = builtins.writeFile "hostname-nix.tpl" "{ ... }: { networking.hostName = "{{ container.name }}"; }";
+              # copy keeps the file updated when the container is changed
+              when = [ "create" "copy" ];
+            };
+            # copy allow the user to specify a custom configuration.nix
+            "configuration-nix" = {
+              enable = true;
+              target = "/etc/nixos/configuration.nix";
+              template = builtins.writeFile "configuration-nix" "{{ config_get(\"user.user-data\", properties.default) }}";
+              when = [ "create" ];
+            };
+          };
+        '';
+      };
+    };
+  };
+
+  config = {
+    system.build.metadata = pkgs.callPackage ../../lib/make-system-tarball.nix {
+      contents = [
+        {
+          source = toYAML "metadata.yaml" {
+            architecture = builtins.elemAt (builtins.match "^([a-z0-9_]+).+" (toString pkgs.system)) 0;
+            creation_date = 1;
+            properties = {
+              description = "${config.system.nixos.distroName} ${config.system.nixos.codeName} ${config.system.nixos.label} ${pkgs.system}";
+              os = "${config.system.nixos.distroId}";
+              release = "${config.system.nixos.codeName}";
+            };
+            templates = templates.properties;
+          };
+          target = "/metadata.yaml";
+        }
+      ] ++ templates.files;
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/virtualisation/lxc-instance-common.nix b/nixpkgs/nixos/modules/virtualisation/lxc-instance-common.nix
new file mode 100644
index 000000000000..d6a0e05fb1c9
--- /dev/null
+++ b/nixpkgs/nixos/modules/virtualisation/lxc-instance-common.nix
@@ -0,0 +1,30 @@
+{lib, ...}:
+
+{
+  imports = [
+    ./lxc-image-metadata.nix
+
+    ../installer/cd-dvd/channel.nix
+    ../profiles/clone-config.nix
+    ../profiles/minimal.nix
+  ];
+
+  # Allow the user to login as root without password.
+  users.users.root.initialHashedPassword = lib.mkOverride 150 "";
+
+  # Some more help text.
+  services.getty.helpLine = ''
+
+    Log in as "root" with an empty password.
+  '';
+
+  # Containers should be light-weight, so start sshd on demand.
+  services.openssh.enable = lib.mkDefault true;
+  services.openssh.startWhenNeeded = lib.mkDefault true;
+
+  # As this is intended as a standalone image, undo some of the minimal profile stuff
+  environment.noXlibs = false;
+  documentation.enable = true;
+  documentation.nixos.enable = true;
+  services.logrotate.enable = true;
+}
diff --git a/nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix b/nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix
new file mode 100644
index 000000000000..ba729465ec2f
--- /dev/null
+++ b/nixpkgs/nixos/modules/virtualisation/lxd-virtual-machine.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+let
+  serialDevice =
+    if pkgs.stdenv.hostPlatform.isx86
+    then "ttyS0"
+    else "ttyAMA0"; # aarch64
+in {
+  imports = [
+    ./lxc-instance-common.nix
+
+    ../profiles/qemu-guest.nix
+  ];
+
+  config = {
+    system.build.qemuImage = import ../../lib/make-disk-image.nix {
+      inherit pkgs lib config;
+
+      partitionTableType = "efi";
+      format = "qcow2-compressed";
+      copyChannel = true;
+    };
+
+    fileSystems = {
+      "/" = {
+        device = "/dev/disk/by-label/nixos";
+        autoResize = true;
+        fsType = "ext4";
+      };
+      "/boot" = {
+        device = "/dev/disk/by-label/ESP";
+        fsType = "vfat";
+      };
+    };
+
+    boot.growPartition = true;
+    boot.loader.systemd-boot.enable = true;
+
+    # image building needs to know what device to install bootloader on
+    boot.loader.grub.device = "/dev/vda";
+
+    boot.kernelParams = ["console=tty1" "console=${serialDevice}"];
+
+    virtualisation.lxd.agent.enable = lib.mkDefault true;
+  };
+}
diff --git a/nixpkgs/nixos/modules/virtualisation/lxd.nix b/nixpkgs/nixos/modules/virtualisation/lxd.nix
index e22ba9a0ae2c..e30fbebb662c 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxd.nix
@@ -2,21 +2,20 @@
 
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.virtualisation.lxd;
+  preseedFormat = pkgs.formats.yaml {};
 in {
   imports = [
-    (mkRemovedOptionModule [ "virtualisation" "lxd" "zfsPackage" ] "Override zfs in an overlay instead to override it globally")
+    (lib.mkRemovedOptionModule [ "virtualisation" "lxd" "zfsPackage" ] "Override zfs in an overlay instead to override it globally")
   ];
 
   ###### interface
 
   options = {
     virtualisation.lxd = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = lib.mdDoc ''
           This option enables lxd, a daemon that manages
@@ -32,28 +31,28 @@ in {
         '';
       };
 
-      package = mkOption {
-        type = types.package;
+      package = lib.mkOption {
+        type = lib.types.package;
         default = pkgs.lxd;
-        defaultText = literalExpression "pkgs.lxd";
+        defaultText = lib.literalExpression "pkgs.lxd";
         description = lib.mdDoc ''
           The LXD package to use.
         '';
       };
 
-      lxcPackage = mkOption {
-        type = types.package;
+      lxcPackage = lib.mkOption {
+        type = lib.types.package;
         default = pkgs.lxc;
-        defaultText = literalExpression "pkgs.lxc";
+        defaultText = lib.literalExpression "pkgs.lxc";
         description = lib.mdDoc ''
           The LXC package to use with LXD (required for AppArmor profiles).
         '';
       };
 
-      zfsSupport = mkOption {
-        type = types.bool;
+      zfsSupport = lib.mkOption {
+        type = lib.types.bool;
         default = config.boot.zfs.enabled;
-        defaultText = literalExpression "config.boot.zfs.enabled";
+        defaultText = lib.literalExpression "config.boot.zfs.enabled";
         description = lib.mdDoc ''
           Enables lxd to use zfs as a storage for containers.
 
@@ -62,8 +61,8 @@ in {
         '';
       };
 
-      recommendedSysctlSettings = mkOption {
-        type = types.bool;
+      recommendedSysctlSettings = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = lib.mdDoc ''
           Enables various settings to avoid common pitfalls when
@@ -75,8 +74,67 @@ in {
         '';
       };
 
-      startTimeout = mkOption {
-        type = types.int;
+      preseed = lib.mkOption {
+        type = lib.types.nullOr (lib.types.submodule {
+          freeformType = preseedFormat.type;
+        });
+
+        default = null;
+
+        description = lib.mdDoc ''
+          Configuration for LXD preseed, see
+          <https://documentation.ubuntu.com/lxd/en/latest/howto/initialize/#initialize-preseed>
+          for supported values.
+
+          Changes to this will be re-applied to LXD which will overwrite existing entities or create missing ones,
+          but entities will *not* be removed by preseed.
+        '';
+
+        example = lib.literalExpression ''
+          {
+            networks = [
+              {
+                name = "lxdbr0";
+                type = "bridge";
+                config = {
+                  "ipv4.address" = "10.0.100.1/24";
+                  "ipv4.nat" = "true";
+                };
+              }
+            ];
+            profiles = [
+              {
+                name = "default";
+                devices = {
+                  eth0 = {
+                    name = "eth0";
+                    network = "lxdbr0";
+                    type = "nic";
+                  };
+                  root = {
+                    path = "/";
+                    pool = "default";
+                    size = "35GiB";
+                    type = "disk";
+                  };
+                };
+              }
+            ];
+            storage_pools = [
+              {
+                name = "default";
+                driver = "dir";
+                config = {
+                  source = "/var/lib/lxd/storage-pools/default";
+                };
+              }
+            ];
+          }
+        '';
+      };
+
+      startTimeout = lib.mkOption {
+        type = lib.types.int;
         default = 600;
         apply = toString;
         description = lib.mdDoc ''
@@ -91,13 +149,13 @@ in {
           Enables the (experimental) LXD UI.
         '');
 
-        package = mkPackageOption pkgs.lxd-unwrapped "ui" { };
+        package = lib.mkPackageOption pkgs.lxd-unwrapped "ui" { };
       };
     };
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     environment.systemPackages = [ cfg.package ];
 
     # Note: the following options are also declared in virtualisation.lxc, but
@@ -139,19 +197,19 @@ in {
       wantedBy = [ "multi-user.target" ];
       after = [
         "network-online.target"
-        (mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
+        (lib.mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
       ];
       requires = [
         "network-online.target"
         "lxd.socket"
-        (mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
+        (lib.mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
       ];
       documentation = [ "man:lxd(1)" ];
 
       path = [ pkgs.util-linux ]
-        ++ optional cfg.zfsSupport config.boot.zfs.package;
+        ++ lib.optional cfg.zfsSupport config.boot.zfs.package;
 
-      environment = mkIf (cfg.ui.enable) {
+      environment = lib.mkIf (cfg.ui.enable) {
         "LXD_UI" = cfg.ui.package;
       };
 
@@ -173,11 +231,26 @@ in {
         # By default, `lxd` loads configuration files from hard-coded
         # `/usr/share/lxc/config` - since this is a no-go for us, we have to
         # explicitly tell it where the actual configuration files are
-        Environment = mkIf (config.virtualisation.lxc.lxcfs.enable)
+        Environment = lib.mkIf (config.virtualisation.lxc.lxcfs.enable)
           "LXD_LXC_TEMPLATE_CONFIG=${pkgs.lxcfs}/share/lxc/config";
       };
     };
 
+    systemd.services.lxd-preseed = lib.mkIf (cfg.preseed != null) {
+      description = "LXD initialization with preseed file";
+      wantedBy = ["multi-user.target"];
+      requires = ["lxd.service"];
+      after = ["lxd.service"];
+
+      script = ''
+        ${pkgs.coreutils}/bin/cat ${preseedFormat.generate "lxd-preseed.yaml" cfg.preseed} | ${cfg.package}/bin/lxd init --preseed
+      '';
+
+      serviceConfig = {
+        Type = "oneshot";
+      };
+    };
+
     users.groups.lxd = {};
 
     users.users.root = {
@@ -185,7 +258,7 @@ in {
       subGidRanges = [ { startGid = 1000000; count = 65536; } ];
     };
 
-    boot.kernel.sysctl = mkIf cfg.recommendedSysctlSettings {
+    boot.kernel.sysctl = lib.mkIf cfg.recommendedSysctlSettings {
       "fs.inotify.max_queued_events" = 1048576;
       "fs.inotify.max_user_instances" = 1048576;
       "fs.inotify.max_user_watches" = 1048576;
@@ -196,7 +269,7 @@ in {
       "kernel.keys.maxkeys" = 2000;
     };
 
-    boot.kernelModules = [ "veth" "xt_comment" "xt_CHECKSUM" "xt_MASQUERADE" ]
-      ++ optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
+    boot.kernelModules = [ "veth" "xt_comment" "xt_CHECKSUM" "xt_MASQUERADE" "vhost_vsock" ]
+      ++ lib.optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
   };
 }
diff --git a/nixpkgs/nixos/release.nix b/nixpkgs/nixos/release.nix
index 6da6faab73be..abaa7ef9a711 100644
--- a/nixpkgs/nixos/release.nix
+++ b/nixpkgs/nixos/release.nix
@@ -44,10 +44,13 @@ let
   pkgs = import ./.. { system = "x86_64-linux"; };
 
 
-  versionModule =
-    { system.nixos.versionSuffix = versionSuffix;
-      system.nixos.revision = nixpkgs.rev or nixpkgs.shortRev;
-    };
+  versionModule = { config, ... }: {
+    system.nixos.versionSuffix = versionSuffix;
+    system.nixos.revision = nixpkgs.rev or nixpkgs.shortRev;
+
+    # At creation time we do not have state yet, so just default to latest.
+    system.stateVersion = config.system.nixos.version;
+  };
 
   makeModules = module: rest: [ configuration versionModule module rest ];
 
@@ -310,7 +313,7 @@ in rec {
   );
 
   # An image that can be imported into lxd and used for container creation
-  lxdImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
+  lxdContainerImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
 
     with import ./.. { inherit system; };
 
@@ -319,14 +322,46 @@ in rec {
       modules =
         [ configuration
           versionModule
-          ./maintainers/scripts/lxd/lxd-image.nix
+          ./maintainers/scripts/lxd/lxd-container-image.nix
         ];
     }).config.system.build.tarball)
 
   );
 
   # Metadata for the lxd image
-  lxdMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
+  lxdContainerMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
+
+    with import ./.. { inherit system; };
+
+    hydraJob ((import lib/eval-config.nix {
+      inherit system;
+      modules =
+        [ configuration
+          versionModule
+          ./maintainers/scripts/lxd/lxd-container-image.nix
+        ];
+    }).config.system.build.metadata)
+
+  );
+
+  # An image that can be imported into lxd and used for container creation
+  lxdVirtualMachineImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
+
+    with import ./.. { inherit system; };
+
+    hydraJob ((import lib/eval-config.nix {
+      inherit system;
+      modules =
+        [ configuration
+          versionModule
+          ./maintainers/scripts/lxd/lxd-virtual-machine-image.nix
+        ];
+    }).config.system.build.qemuImage)
+
+  );
+
+  # Metadata for the lxd image
+  lxdVirtualMachineImageMeta = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
 
     with import ./.. { inherit system; };
 
@@ -335,7 +370,7 @@ in rec {
       modules =
         [ configuration
           versionModule
-          ./maintainers/scripts/lxd/lxd-image.nix
+          ./maintainers/scripts/lxd/lxd-virtual-machine-image.nix
         ];
     }).config.system.build.metadata)
 
diff --git a/nixpkgs/nixos/tests/akkoma.nix b/nixpkgs/nixos/tests/akkoma.nix
index 7115c0beed34..287e2d485999 100644
--- a/nixpkgs/nixos/tests/akkoma.nix
+++ b/nixpkgs/nixos/tests/akkoma.nix
@@ -33,7 +33,10 @@ let
 
     echo '${userPassword}' | ${pkgs.toot}/bin/toot login_cli -i "akkoma.nixos.test" -e "jamy@nixos.test"
     echo "y" | ${pkgs.toot}/bin/toot post "hello world Jamy here"
-    echo "y" | ${pkgs.toot}/bin/toot timeline | grep -F -q "hello world Jamy here"
+
+    # Retrieving timeline with toot currently broken due to incompatible timestamp format
+    # cf. <https://akkoma.dev/AkkomaGang/akkoma/issues/637> and <https://github.com/ihabunek/toot/issues/399>
+    #echo "y" | ${pkgs.toot}/bin/toot timeline | grep -F -q "hello world Jamy here"
 
     # Test file upload
     echo "y" | ${pkgs.toot}/bin/toot upload <(dd if=/dev/zero bs=1024 count=1024 status=none) \
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index c1e124bda5c7..0037fb189366 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -109,6 +109,7 @@ in {
   allTerminfo = handleTest ./all-terminfo.nix {};
   alps = handleTest ./alps.nix {};
   amazon-init-shell = handleTest ./amazon-init-shell.nix {};
+  anbox = runTest ./anbox.nix;
   anuko-time-tracker = handleTest ./anuko-time-tracker.nix {};
   apcupsd = handleTest ./apcupsd.nix {};
   apfs = runTest ./apfs.nix;
@@ -210,6 +211,7 @@ in {
   custom-ca = handleTest ./custom-ca.nix {};
   croc = handleTest ./croc.nix {};
   darling = handleTest ./darling.nix {};
+  dae = handleTest ./dae.nix {};
   dconf = handleTest ./dconf.nix {};
   deepin = handleTest ./deepin.nix {};
   deluge = handleTest ./deluge.nix {};
@@ -395,7 +397,7 @@ in {
   jibri = handleTest ./jibri.nix {};
   jirafeau = handleTest ./jirafeau.nix {};
   jitsi-meet = handleTest ./jitsi-meet.nix {};
-  jool = handleTest ./jool.nix {};
+  jool = import ./jool.nix { inherit pkgs runTest; };
   k3s = handleTest ./k3s {};
   kafka = handleTest ./kafka.nix {};
   kanidm = handleTest ./kanidm.nix {};
@@ -446,7 +448,7 @@ in {
   loki = handleTest ./loki.nix {};
   luks = handleTest ./luks.nix {};
   lvm2 = handleTest ./lvm2 {};
-  lxd = pkgs.recurseIntoAttrs (handleTest ./lxd {});
+  lxd = pkgs.recurseIntoAttrs (handleTest ./lxd { inherit handleTestOn; });
   lxd-image-server = handleTest ./lxd-image-server.nix {};
   #logstash = handleTest ./logstash.nix {};
   lorri = handleTest ./lorri/default.nix {};
@@ -483,6 +485,7 @@ in {
   miriway = handleTest ./miriway.nix {};
   misc = handleTest ./misc.nix {};
   mjolnir = handleTest ./matrix/mjolnir.nix {};
+  mobilizon = handleTest ./mobilizon.nix {};
   mod_perl = handleTest ./mod_perl.nix {};
   molly-brown = handleTest ./molly-brown.nix {};
   monica = handleTest ./web-apps/monica.nix {};
@@ -728,6 +731,7 @@ in {
   sslh = handleTest ./sslh.nix {};
   sssd = handleTestOn ["x86_64-linux"] ./sssd.nix {};
   sssd-ldap = handleTestOn ["x86_64-linux"] ./sssd-ldap.nix {};
+  stalwart-mail = handleTest ./stalwart-mail.nix {};
   stargazer = runTest ./web-servers/stargazer.nix;
   starship = handleTest ./starship.nix {};
   static-web-server = handleTest ./web-servers/static-web-server.nix {};
diff --git a/nixpkgs/nixos/tests/anbox.nix b/nixpkgs/nixos/tests/anbox.nix
new file mode 100644
index 000000000000..d78f63ec761f
--- /dev/null
+++ b/nixpkgs/nixos/tests/anbox.nix
@@ -0,0 +1,40 @@
+{ lib, pkgs, ... }:
+
+{
+  name = "anbox";
+  meta.maintainers = with lib.maintainers; [ mvnetbiz ];
+
+  nodes.machine = { pkgs, config, ... }: {
+    imports = [
+      ./common/user-account.nix
+      ./common/x11.nix
+    ];
+
+    environment.systemPackages = with pkgs; [ android-tools ];
+
+    test-support.displayManager.auto.user = "alice";
+
+    virtualisation.anbox.enable = true;
+    boot.kernelPackages = pkgs.linuxPackages_5_15;
+
+    # The AArch64 anbox image will not start.
+    # Meanwhile the postmarketOS images work just fine.
+    virtualisation.anbox.image = pkgs.anbox.postmarketos-image;
+    virtualisation.memorySize = 2500;
+  };
+
+  testScript = { nodes, ... }: let
+    user = nodes.machine.users.users.alice;
+    bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${toString user.uid}/bus";
+  in ''
+    machine.wait_for_x()
+
+    machine.wait_until_succeeds(
+        "sudo -iu alice ${bus} anbox wait-ready"
+    )
+
+    machine.wait_until_succeeds("adb shell true")
+
+    print(machine.succeed("adb devices"))
+  '';
+}
diff --git a/nixpkgs/nixos/tests/custom-ca.nix b/nixpkgs/nixos/tests/custom-ca.nix
index 25a7b6fdea46..0fcdf81022d7 100644
--- a/nixpkgs/nixos/tests/custom-ca.nix
+++ b/nixpkgs/nixos/tests/custom-ca.nix
@@ -131,8 +131,8 @@ let
         # chromium-based browsers refuse to run as root
         test-support.displayManager.auto.user = "alice";
 
-        # browsers may hang with the default memory
-        virtualisation.memorySize = 600;
+        # machine often runs out of memory with less
+        virtualisation.memorySize = 1024;
 
         environment.systemPackages = [ pkgs.xdotool pkgs.${browser} ];
       };
diff --git a/nixpkgs/nixos/tests/dae.nix b/nixpkgs/nixos/tests/dae.nix
new file mode 100644
index 000000000000..b8c8ebce7457
--- /dev/null
+++ b/nixpkgs/nixos/tests/dae.nix
@@ -0,0 +1,29 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }: {
+
+  name = "dae";
+
+  meta = {
+    maintainers = with lib.maintainers; [ oluceps ];
+  };
+
+  nodes.machine = { pkgs, ... }: {
+    environment.systemPackages = [ pkgs.curl ];
+    services.nginx = {
+      enable = true;
+      statusPage = true;
+    };
+    services.dae = {
+      enable = true;
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("nginx.service")
+    machine.wait_for_unit("dae.service")
+
+    machine.wait_for_open_port(80)
+
+    machine.succeed("curl --fail --max-time 10 http://localhost")
+  '';
+
+})
diff --git a/nixpkgs/nixos/tests/jool.nix b/nixpkgs/nixos/tests/jool.nix
index 6d5ded9b18e0..93575f07b1c8 100644
--- a/nixpkgs/nixos/tests/jool.nix
+++ b/nixpkgs/nixos/tests/jool.nix
@@ -1,9 +1,4 @@
-{ system ? builtins.currentSystem,
-  config ? {},
-  pkgs ? import ../.. { inherit system config; }
-}:
-
-with import ../lib/testing-python.nix { inherit system pkgs; };
+{ pkgs, runTest }:
 
 let
   inherit (pkgs) lib;
@@ -23,7 +18,6 @@ let
       description = "Mock webserver";
       wants = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
-      serviceConfig.Restart = "always";
       script = ''
         while true; do
         {
@@ -40,7 +34,7 @@ let
 in
 
 {
-  siit = makeTest {
+  siit = runTest {
     # 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.
@@ -49,8 +43,7 @@ in
     meta.maintainers = with lib.maintainers; [ rnhmjoj ];
 
     # Border relay
-    nodes.relay = { ... }: {
-      imports = [ ../modules/profiles/minimal.nix ];
+    nodes.relay = {
       virtualisation.vlans = [ 1 2 ];
 
       # Enable packet routing
@@ -65,20 +58,13 @@ in
         eth2.ipv4.addresses = [ { address = "192.0.2.1";  prefixLength = 24; } ];
       };
 
-      networking.jool = {
-        enable = true;
-        siit.enable = true;
-        siit.config.global.pool6 = "fd::/96";
-      };
+      networking.jool.enable = true;
+      networking.jool.siit.default.global.pool6 = "fd::/96";
     };
 
     # IPv6 only node
-    nodes.alice = { ... }: {
-      imports = [
-        ../modules/profiles/minimal.nix
-        ipv6Only
-        (webserver 6 "Hello, Bob!")
-      ];
+    nodes.alice = {
+      imports = [ ipv6Only (webserver 6 "Hello, Bob!") ];
 
       virtualisation.vlans = [ 1 ];
       networking.interfaces.eth1.ipv6 = {
@@ -89,12 +75,8 @@ in
     };
 
     # IPv4 only node
-    nodes.bob = { ... }: {
-      imports = [
-        ../modules/profiles/minimal.nix
-        ipv4Only
-        (webserver 4 "Hello, Alice!")
-      ];
+    nodes.bob = {
+      imports = [ ipv4Only (webserver 4 "Hello, Alice!") ];
 
       virtualisation.vlans = [ 2 ];
       networking.interfaces.eth1.ipv4 = {
@@ -107,17 +89,17 @@ in
     testScript = ''
       start_all()
 
-      relay.wait_for_unit("jool-siit.service")
+      relay.wait_for_unit("jool-siit-default.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")
+        relay.systemctl("stop jool-siit-default.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")
+        relay.systemctl("start jool-siit-default.service")
         alice.wait_until_succeeds("ping -c1 fd::192.0.2.16")
         bob.wait_until_succeeds("ping -c1 198.51.100.8")
 
@@ -132,7 +114,7 @@ in
     '';
   };
 
-  nat64 = makeTest {
+  nat64 = runTest {
     # 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
@@ -142,8 +124,7 @@ in
     meta.maintainers = with lib.maintainers; [ rnhmjoj ];
 
     # Router
-    nodes.router = { ... }: {
-      imports = [ ../modules/profiles/minimal.nix ];
+    nodes.router = {
       virtualisation.vlans = [ 1 2 ];
 
       # Enable packet routing
@@ -158,32 +139,29 @@ in
         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"; }
-          ];
-        };
+      networking.jool.enable = true;
+      networking.jool.nat64.default = {
+        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 ];
+    nodes.client = {
+      imports = [ ipv6Only ];
       virtualisation.vlans = [ 1 ];
 
       networking.interfaces.eth1.ipv6 = {
@@ -194,12 +172,8 @@ in
     };
 
     # LAN server (IPv6 only)
-    nodes.homeserver = { ... }: {
-      imports = [
-        ../modules/profiles/minimal.nix
-        ipv6Only
-        (webserver 6 "Hello from IPv6!")
-      ];
+    nodes.homeserver = {
+      imports = [ ipv6Only (webserver 6 "Hello from IPv6!") ];
 
       virtualisation.vlans = [ 1 ];
       networking.interfaces.eth1.ipv6 = {
@@ -210,12 +184,8 @@ in
     };
 
     # WAN server (IPv4 only)
-    nodes.server = { ... }: {
-      imports = [
-        ../modules/profiles/minimal.nix
-        ipv4Only
-        (webserver 4 "Hello from IPv4!")
-      ];
+    nodes.server = {
+      imports = [ ipv4Only (webserver 4 "Hello from IPv4!") ];
 
       virtualisation.vlans = [ 2 ];
       networking.interfaces.eth1.ipv4.addresses =
@@ -229,7 +199,7 @@ in
         node.wait_for_unit("network-addresses-eth1.service")
 
       with subtest("Client can ping the WAN server"):
-        router.wait_for_unit("jool-nat64.service")
+        router.wait_for_unit("jool-nat64-default.service")
         client.succeed("ping -c1 64:ff9b::203.0.113.16")
 
       with subtest("Client can connect to the WAN webserver"):
diff --git a/nixpkgs/nixos/tests/lxd/container.nix b/nixpkgs/nixos/tests/lxd/container.nix
index 9e56f6e41e05..bdaaebfc0028 100644
--- a/nixpkgs/nixos/tests/lxd/container.nix
+++ b/nixpkgs/nixos/tests/lxd/container.nix
@@ -1,7 +1,7 @@
 import ../make-test-python.nix ({ pkgs, lib, ... } :
 
 let
-  lxd-image = import ../../release.nix {
+  releases = import ../../release.nix {
     configuration = {
       # Building documentation makes the test unnecessarily take a longer time:
       documentation.enable = lib.mkForce false;
@@ -11,14 +11,14 @@ let
     };
   };
 
-  lxd-image-metadata = lxd-image.lxdMeta.${pkgs.stdenv.hostPlatform.system};
-  lxd-image-rootfs = lxd-image.lxdImage.${pkgs.stdenv.hostPlatform.system};
+  lxd-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system};
+  lxd-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system};
 
 in {
-  name = "lxd";
+  name = "lxd-container";
 
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ patryk27 ];
+    maintainers = [ patryk27 adamcstephens ];
   };
 
   nodes.machine = { lib, ... }: {
@@ -49,6 +49,9 @@ in {
     # Wait for lxd to settle
     machine.succeed("lxd waitready")
 
+    # no preseed should mean no service
+    machine.fail("systemctl status lxd-preseed.service")
+
     machine.succeed("lxd init --minimal")
 
     machine.succeed(
diff --git a/nixpkgs/nixos/tests/lxd/default.nix b/nixpkgs/nixos/tests/lxd/default.nix
index 2e34907d7936..20afdd5e48bb 100644
--- a/nixpkgs/nixos/tests/lxd/default.nix
+++ b/nixpkgs/nixos/tests/lxd/default.nix
@@ -2,8 +2,11 @@
   system ? builtins.currentSystem,
   config ? {},
   pkgs ? import ../../.. {inherit system config;},
+  handleTestOn,
 }: {
   container = import ./container.nix {inherit system pkgs;};
   nftables = import ./nftables.nix {inherit system pkgs;};
+  preseed = import ./preseed.nix {inherit system pkgs;};
   ui = import ./ui.nix {inherit system pkgs;};
+  virtual-machine = handleTestOn ["x86_64-linux"] ./virtual-machine.nix { inherit system pkgs; };
 }
diff --git a/nixpkgs/nixos/tests/lxd/preseed.nix b/nixpkgs/nixos/tests/lxd/preseed.nix
new file mode 100644
index 000000000000..7d89b9f56daa
--- /dev/null
+++ b/nixpkgs/nixos/tests/lxd/preseed.nix
@@ -0,0 +1,71 @@
+import ../make-test-python.nix ({ pkgs, lib, ... } :
+
+{
+  name = "lxd-preseed";
+
+  meta = {
+    maintainers = with lib.maintainers; [ adamcstephens ];
+  };
+
+  nodes.machine = { lib, ... }: {
+    virtualisation = {
+      diskSize = 4096;
+
+      lxc.lxcfs.enable = true;
+      lxd.enable = true;
+
+      lxd.preseed = {
+        networks = [
+          {
+            name = "nixostestbr0";
+            type = "bridge";
+            config = {
+              "ipv4.address" = "10.0.100.1/24";
+              "ipv4.nat" = "true";
+            };
+          }
+        ];
+        profiles = [
+          {
+            name = "nixostest_default";
+            devices = {
+              eth0 = {
+                name = "eth0";
+                network = "nixostestbr0";
+                type = "nic";
+              };
+              root = {
+                path = "/";
+                pool = "default";
+                size = "35GiB";
+                type = "disk";
+              };
+            };
+          }
+        ];
+        storage_pools = [
+          {
+            name = "nixostest_pool";
+            driver = "dir";
+          }
+        ];
+      };
+    };
+  };
+
+  testScript = ''
+    def wait_for_preseed(_) -> bool:
+      _, output = machine.systemctl("is-active lxd-preseed.service")
+      return ("inactive" in output)
+
+    machine.wait_for_unit("sockets.target")
+    machine.wait_for_unit("lxd.service")
+    with machine.nested("Waiting for preseed to complete"):
+      retry(wait_for_preseed)
+
+    with subtest("Verify preseed resources created"):
+      machine.succeed("lxc profile show nixostest_default")
+      machine.succeed("lxc network info nixostestbr0")
+      machine.succeed("lxc storage show nixostest_pool")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/lxd/virtual-machine.nix b/nixpkgs/nixos/tests/lxd/virtual-machine.nix
new file mode 100644
index 000000000000..93705e9350c5
--- /dev/null
+++ b/nixpkgs/nixos/tests/lxd/virtual-machine.nix
@@ -0,0 +1,64 @@
+import ../make-test-python.nix ({ pkgs, lib, ... }:
+
+let
+  releases = import ../../release.nix {
+    configuration = {
+      # Building documentation makes the test unnecessarily take a longer time:
+      documentation.enable = lib.mkForce false;
+
+      # Our tests require `grep` & friends:
+      environment.systemPackages = with pkgs; [busybox];
+    };
+  };
+
+  lxd-image-metadata = releases.lxdVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system};
+  lxd-image-disk = releases.lxdVirtualMachineImage.${pkgs.stdenv.hostPlatform.system};
+
+  instance-name = "instance1";
+in {
+  name = "lxd-virtual-machine";
+
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [adamcstephens];
+  };
+
+  nodes.machine = {lib, ...}: {
+    virtualisation = {
+      diskSize = 4096;
+
+      cores = 2;
+
+      # Ensure we have enough memory for the nested virtual machine
+      memorySize = 1024;
+
+      lxc.lxcfs.enable = true;
+      lxd.enable = true;
+    };
+  };
+
+  testScript = ''
+    def instance_is_up(_) -> bool:
+      status, _ = machine.execute("lxc exec ${instance-name} --disable-stdin --force-interactive /run/current-system/sw/bin/true")
+      return status == 0
+
+    machine.wait_for_unit("sockets.target")
+    machine.wait_for_unit("lxd.service")
+    machine.wait_for_file("/var/lib/lxd/unix.socket")
+
+    # Wait for lxd to settle
+    machine.succeed("lxd waitready")
+
+    machine.succeed("lxd init --minimal")
+
+    with subtest("virtual-machine image can be imported"):
+        machine.succeed("lxc image import ${lxd-image-metadata}/*/*.tar.xz ${lxd-image-disk}/nixos.qcow2 --alias nixos")
+
+    with subtest("virtual-machine can be launched and become available"):
+        machine.succeed("lxc launch nixos ${instance-name} --vm --config limits.memory=512MB --config security.secureboot=false")
+        with machine.nested("Waiting for instance to start and be usable"):
+          retry(instance_is_up)
+
+    with subtest("lxd-agent is started"):
+        machine.succeed("lxc exec ${instance-name} systemctl is-active lxd-agent")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/mobilizon.nix b/nixpkgs/nixos/tests/mobilizon.nix
new file mode 100644
index 000000000000..2b070ca9d960
--- /dev/null
+++ b/nixpkgs/nixos/tests/mobilizon.nix
@@ -0,0 +1,44 @@
+import ./make-test-python.nix ({ lib, ... }:
+  let
+    certs = import ./common/acme/server/snakeoil-certs.nix;
+    mobilizonDomain = certs.domain;
+    port = 41395;
+  in
+
+  {
+    name = "mobilizon";
+    meta.maintainers = with lib.maintainers; [ minijackson erictapen ];
+
+    nodes.server =
+      { ... }:
+      {
+        services.mobilizon = {
+          enable = true;
+          settings = {
+            ":mobilizon" = {
+              ":instance" = {
+                name = "Test Mobilizon";
+                hostname = mobilizonDomain;
+              };
+              "Mobilizon.Web.Endpoint".http.port = port;
+            };
+          };
+        };
+
+        security.pki.certificateFiles = [ certs.ca.cert ];
+
+        services.nginx.virtualHosts."${mobilizonDomain}" = {
+          enableACME = lib.mkForce false;
+          sslCertificate = certs.${mobilizonDomain}.cert;
+          sslCertificateKey = certs.${mobilizonDomain}.key;
+        };
+
+        networking.hosts."::1" = [ mobilizonDomain ];
+      };
+
+    testScript = ''
+      server.wait_for_unit("mobilizon.service")
+      server.wait_for_open_port(${toString port})
+      server.succeed("curl --fail https://${mobilizonDomain}/")
+    '';
+  })
diff --git a/nixpkgs/nixos/tests/stalwart-mail.nix b/nixpkgs/nixos/tests/stalwart-mail.nix
new file mode 100644
index 000000000000..b5589966a160
--- /dev/null
+++ b/nixpkgs/nixos/tests/stalwart-mail.nix
@@ -0,0 +1,117 @@
+# Rudimentary test checking that the Stalwart email server can:
+# - receive some message through SMTP submission, then
+# - serve this message through IMAP.
+
+let
+  certs = import ./common/acme/server/snakeoil-certs.nix;
+  domain = certs.domain;
+
+in import ./make-test-python.nix ({ lib, ... }: {
+  name = "stalwart-mail";
+
+  nodes.main = { pkgs, ... }: {
+    security.pki.certificateFiles = [ certs.ca.cert ];
+
+    services.stalwart-mail = {
+      enable = true;
+      settings = {
+        server.hostname = domain;
+
+        certificate."snakeoil" = {
+          cert = "file://${certs.${domain}.cert}";
+          private-key = "file://${certs.${domain}.key}";
+        };
+
+        server.tls = {
+          certificate = "snakeoil";
+          enable = true;
+          implicit = false;
+        };
+
+        server.listener = {
+          "smtp-submission" = {
+            bind = [ "[::]:587" ];
+            protocol = "smtp";
+          };
+
+          "imap" = {
+            bind = [ "[::]:143" ];
+            protocol = "imap";
+          };
+        };
+
+        session.auth.mechanisms = [ "PLAIN" ];
+        session.auth.directory = "in-memory";
+        jmap.directory = "in-memory";  # shared with imap
+
+        session.rcpt.directory = "in-memory";
+        queue.outbound.next-hop = [ "local" ];
+
+        directory."in-memory" = {
+          type = "memory";
+          users = [
+            {
+              name = "alice";
+              secret = "foobar";
+              email = [ "alice@${domain}" ];
+            }
+            {
+              name = "bob";
+              secret = "foobar";
+              email = [ "bob@${domain}" ];
+            }
+          ];
+        };
+      };
+    };
+
+    environment.systemPackages = [
+      (pkgs.writers.writePython3Bin "test-smtp-submission" { } ''
+        from smtplib import SMTP
+
+        with SMTP('localhost', 587) as smtp:
+            smtp.starttls()
+            smtp.login('alice', 'foobar')
+            smtp.sendmail(
+                'alice@${domain}',
+                'bob@${domain}',
+                """
+                    From: alice@${domain}
+                    To: bob@${domain}
+                    Subject: Some test message
+
+                    This is a test message.
+                """.strip()
+            )
+      '')
+
+      (pkgs.writers.writePython3Bin "test-imap-read" { } ''
+        from imaplib import IMAP4
+
+        with IMAP4('localhost') as imap:
+            imap.starttls()
+            imap.login('bob', 'foobar')
+            imap.select('"All Mail"')
+            status, [ref] = imap.search(None, 'ALL')
+            assert status == 'OK'
+            [msgId] = ref.split()
+            status, msg = imap.fetch(msgId, 'BODY[TEXT]')
+            assert status == 'OK'
+            assert msg[0][1].strip() == b'This is a test message.'
+      '')
+    ];
+  };
+
+  testScript = /* python */ ''
+    main.wait_for_unit("stalwart-mail.service")
+    main.wait_for_open_port(587)
+    main.wait_for_open_port(143)
+
+    main.succeed("test-smtp-submission")
+    main.succeed("test-imap-read")
+  '';
+
+  meta = {
+    maintainers = with lib.maintainers; [ happysalada pacien ];
+  };
+})
diff --git a/nixpkgs/nixos/tests/user-activation-scripts.nix b/nixpkgs/nixos/tests/user-activation-scripts.nix
index 5df072ce0508..ebd96b019e92 100644
--- a/nixpkgs/nixos/tests/user-activation-scripts.nix
+++ b/nixpkgs/nixos/tests/user-activation-scripts.nix
@@ -8,6 +8,7 @@ import ./make-test-python.nix ({ lib, ... }: {
       initialPassword = "pass1";
       isNormalUser = true;
     };
+    systemd.user.tmpfiles.users.alice.rules = [ "r %h/file-to-remove" ];
   };
 
   testScript = ''
@@ -27,7 +28,9 @@ import ./make-test-python.nix ({ lib, ... }: {
     machine.wait_for_file("/home/alice/login-ok")
     verify_user_activation_run_count(1)
 
+    machine.succeed("touch /home/alice/file-to-remove")
     machine.succeed("/run/current-system/bin/switch-to-configuration test")
     verify_user_activation_run_count(2)
+    machine.succeed("[[ ! -f /home/alice/file-to-remove ]] || false")
   '';
 })