about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2023-07-22 12:01:28 +0000
committerGitHub <noreply@github.com>2023-07-22 12:01:28 +0000
commit045f0259febde0ca2e4c55f87f5f09609558aa09 (patch)
treec4dd657566d218e1ce892c38313a71d6725c3aa8
parented71ea2d5ff9fe94069c4794bc961b72d61e65ef (diff)
parentf465da166263bc0d4b39dfd4ca28b777c92d4b73 (diff)
Merge master into staging-next
-rw-r--r--nixos/doc/manual/release-notes/rl-2311.section.md3
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/backup/borgbackup.nix2
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/default.nix6
-rw-r--r--nixos/modules/services/databases/pgbouncer.nix632
-rw-r--r--nixos/modules/services/misc/cgminer.nix2
-rw-r--r--nixos/modules/services/misc/sourcehut/default.nix6
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/pve.nix12
-rw-r--r--nixos/modules/services/networking/biboumi.nix3
-rw-r--r--nixos/modules/services/networking/cjdns.nix2
-rw-r--r--nixos/modules/services/networking/libreswan.nix4
-rw-r--r--nixos/modules/services/networking/murmur.nix20
-rw-r--r--nixos/modules/services/networking/nsd.nix4
-rw-r--r--nixos/modules/services/networking/ssh/lshd.nix4
-rw-r--r--nixos/modules/services/scheduling/fcron.nix2
-rw-r--r--nixos/modules/services/web-apps/invidious.nix2
-rw-r--r--nixos/modules/services/web-apps/invoiceplane.nix2
-rw-r--r--nixos/modules/services/web-apps/peertube.nix2
-rw-r--r--nixos/modules/services/web-servers/lighttpd/cgit.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/phosh.nix2
-rw-r--r--nixos/modules/system/boot/kernel_config.nix7
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix4
-rw-r--r--nixos/modules/system/boot/systemd/user.nix2
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/pgbouncer.nix61
-rw-r--r--pkgs/applications/editors/texmacs/darwin.nix8
-rw-r--r--pkgs/applications/editors/vscode/vscodium.nix2
-rw-r--r--pkgs/applications/misc/mkgmap/default.nix4
-rw-r--r--pkgs/applications/networking/browsers/chromium/default.nix4
-rw-r--r--pkgs/applications/networking/browsers/firefox/common.nix1
-rw-r--r--pkgs/applications/networking/browsers/microsoft-edge/browser.nix8
-rw-r--r--pkgs/applications/networking/flexget/default.nix4
-rw-r--r--pkgs/applications/office/libreoffice/default.nix2
-rw-r--r--pkgs/applications/office/trilium/desktop.nix1
-rw-r--r--pkgs/applications/science/logic/hol_light/default.nix3
-rw-r--r--pkgs/applications/science/math/sage/sage-tests.nix2
-rw-r--r--pkgs/applications/version-management/sapling/default.nix2
-rw-r--r--pkgs/applications/video/obs-studio/plugins/obs-vertical-canvas.nix4
-rw-r--r--pkgs/applications/window-managers/sway/wrapper.nix2
-rw-r--r--pkgs/build-support/bintools-wrapper/default.nix16
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix14
-rw-r--r--pkgs/build-support/docker/default.nix2
-rw-r--r--pkgs/build-support/fetchgithub/default.nix2
-rw-r--r--pkgs/build-support/kernel/make-initrd-ng.nix2
-rw-r--r--pkgs/build-support/nix-gitignore/default.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate/configure-crate.nix2
-rw-r--r--pkgs/build-support/vm/default.nix2
-rw-r--r--pkgs/data/sgml+xml/stylesheets/xslt/docbook-xsl/default.nix2
-rw-r--r--pkgs/development/compilers/purescript/purescript/default.nix5
-rw-r--r--pkgs/development/interpreters/acl2/libipasirglucose4/default.nix2
-rw-r--r--pkgs/development/interpreters/python/mk-python-derivation.nix2
-rw-r--r--pkgs/development/interpreters/python/wrapper.nix2
-rw-r--r--pkgs/development/libraries/ffmpeg/generic.nix2
-rw-r--r--pkgs/development/libraries/liblcf/default.nix30
-rw-r--r--pkgs/development/libraries/opencv/tests.nix2
-rw-r--r--pkgs/development/libraries/qt-4.x/4.8/default.nix6
-rw-r--r--pkgs/development/mobile/titaniumenv/build-app.nix3
-rw-r--r--pkgs/development/python-modules/azure-common/default.nix2
-rw-r--r--pkgs/development/python-modules/azure-mgmt-common/default.nix2
-rw-r--r--pkgs/development/python-modules/hcloud/default.nix4
-rw-r--r--pkgs/development/python-modules/pyfuse3/default.nix4
-rw-r--r--pkgs/development/python-modules/pymilvus/default.nix4
-rw-r--r--pkgs/development/python-modules/rauth/default.nix54
-rw-r--r--pkgs/development/python-modules/tensorflow/bin.nix2
-rw-r--r--pkgs/development/python-modules/types-deprecated/default.nix4
-rw-r--r--pkgs/development/ruby-modules/bundled-common/default.nix11
-rw-r--r--pkgs/development/ruby-modules/gem/default.nix2
-rw-r--r--pkgs/development/tools/flyway/default.nix4
-rw-r--r--pkgs/development/tools/misc/distcc/default.nix2
-rw-r--r--pkgs/development/web/nodejs/v20.nix4
-rw-r--r--pkgs/games/easyrpg-player/default.nix112
-rw-r--r--pkgs/os-specific/linux/kernel/manual-config.nix5
-rw-r--r--pkgs/servers/mail/mox/default.nix34
-rw-r--r--pkgs/servers/mail/mox/version.patch45
-rw-r--r--pkgs/servers/miniflux/default.nix6
-rw-r--r--pkgs/servers/sql/pgbouncer/default.nix6
-rw-r--r--pkgs/shells/zsh/grml-zsh-config/default.nix4
-rw-r--r--pkgs/tools/admin/eksctl/default.nix6
-rw-r--r--pkgs/tools/networking/ebpf-verifier/default.nix60
-rw-r--r--pkgs/tools/networking/ebpf-verifier/remove-fetchcontent-usage.patch14
-rw-r--r--pkgs/tools/security/cnspec/default.nix6
-rw-r--r--pkgs/tools/security/jadx/default.nix45
-rw-r--r--pkgs/tools/text/fanficfare/default.nix4
-rw-r--r--pkgs/top-level/all-packages.nix17
-rw-r--r--pkgs/top-level/python-packages.nix2
85 files changed, 1222 insertions, 176 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md
index d94f5fceb5f36..7668abe6174ff 100644
--- a/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -24,12 +24,15 @@
 
 - [Apache Guacamole](https://guacamole.apache.org/), a cross-platform, clientless remote desktop gateway. Available as [services.guacamole-server](#opt-services.guacamole-server.enable) and [services.guacamole-client](#opt-services.guacamole-client.enable) services.
 
+- [pgBouncer](https://www.pgbouncer.org), a PostgreSQL connection pooler. Available as [services.pgbouncer](#opt-services.pgbouncer.enable).
+
 - [trust-dns](https://trust-dns.org/), a Rust based DNS server built to be safe and secure from the ground up. Available as [services.trust-dns](#opt-services.trust-dns.enable).
 
 - [osquery](https://www.osquery.io/), a SQL powered operating system instrumentation, monitoring, and analytics.
 
 - [ebusd](https://ebusd.eu), a daemon for handling communication with eBUS devices connected to a 2-wire bus system (“energy bus” used by numerous heating systems). Available as [services.ebusd](#opt-services.ebusd.enable).
 
+
 ## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
 
 - The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index b7a7e051e5b96..06a84abbdfb76 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -418,6 +418,7 @@
   ./services/databases/neo4j.nix
   ./services/databases/openldap.nix
   ./services/databases/opentsdb.nix
+  ./services/databases/pgbouncer.nix
   ./services/databases/pgmanage.nix
   ./services/databases/postgresql.nix
   ./services/databases/redis.nix
diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix
index 0da70112d48dd..3b44f097ab791 100644
--- a/nixos/modules/services/backup/borgbackup.nix
+++ b/nixos/modules/services/backup/borgbackup.nix
@@ -33,7 +33,7 @@ let
     }
     trap on_exit EXIT
 
-    archiveName="${if cfg.archiveBaseName == null then "" else cfg.archiveBaseName + "-"}$(date ${cfg.dateFormat})"
+    archiveName="${optionalString (cfg.archiveBaseName != null) (cfg.archiveBaseName + "-")}$(date ${cfg.dateFormat})"
     archiveSuffix="${optionalString cfg.appendFailedSuffix ".failed"}"
     ${cfg.preHook}
   '' + optionalString cfg.doInit ''
diff --git a/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix
index a9a587b41e881..e4d54b0cb0f49 100644
--- a/nixos/modules/services/continuous-integration/jenkins/default.nix
+++ b/nixos/modules/services/continuous-integration/jenkins/default.nix
@@ -210,9 +210,7 @@ in {
 
       preStart =
         let replacePlugins =
-              if cfg.plugins == null
-              then ""
-              else
+              optionalString (cfg.plugins != null) (
                 let pluginCmds = lib.attrsets.mapAttrsToList
                       (n: v: "cp ${v} ${cfg.home}/plugins/${n}.jpi")
                       cfg.plugins;
@@ -220,7 +218,7 @@ in {
                   rm -r ${cfg.home}/plugins || true
                   mkdir -p ${cfg.home}/plugins
                   ${lib.strings.concatStringsSep "\n" pluginCmds}
-                '';
+                '');
         in ''
           rm -rf ${cfg.home}/war
           ${replacePlugins}
diff --git a/nixos/modules/services/databases/pgbouncer.nix b/nixos/modules/services/databases/pgbouncer.nix
new file mode 100644
index 0000000000000..1aec03c114d1a
--- /dev/null
+++ b/nixos/modules/services/databases/pgbouncer.nix
@@ -0,0 +1,632 @@
+{ lib, pkgs, config, ... } :
+
+with lib;
+
+let
+  cfg = config.services.pgbouncer;
+
+  confFile = pkgs.writeTextFile {
+    name = "pgbouncer.ini";
+    text =  ''
+      [databases]
+      ${concatStringsSep "\n"
+      (mapAttrsToList (dbname : settings : "${dbname} = ${settings}") cfg.databases)}
+
+      [users]
+      ${concatStringsSep "\n"
+      (mapAttrsToList (username : settings : "${username} = ${settings}") cfg.users)}
+
+      [peers]
+      ${concatStringsSep "\n"
+      (mapAttrsToList (peerid : settings : "${peerid} = ${settings}") cfg.peers)}
+
+      [pgbouncer]
+      # general
+      ${optionalString (cfg.ignoreStartupParameters != null) "ignore_startup_parameters = ${cfg.ignoreStartupParameters}"}
+      listen_port = ${toString cfg.listenPort}
+      ${optionalString (cfg.listenAddress != null) "listen_addr = ${cfg.listenAddress}"}
+      pool_mode = ${cfg.poolMode}
+      max_client_conn = ${toString cfg.maxClientConn}
+      default_pool_size = ${toString cfg.defaultPoolSize}
+      max_user_connections = ${toString cfg.maxUserConnections}
+      max_db_connections = ${toString cfg.maxDbConnections}
+
+      #auth
+      auth_type = ${cfg.authType}
+      ${optionalString (cfg.authHbaFile != null) "auth_hba_file = ${cfg.authHbaFile}"}
+      ${optionalString (cfg.authFile != null) "auth_file = ${cfg.authFile}"}
+      ${optionalString (cfg.authUser != null) "auth_user = ${cfg.authUser}"}
+      ${optionalString (cfg.authQuery != null) "auth_query = ${cfg.authQuery}"}
+      ${optionalString (cfg.authDbname != null) "auth_dbname = ${cfg.authDbname}"}
+
+      # TLS
+      ${optionalString (cfg.tls.client != null) ''
+      client_tls_sslmode = ${cfg.tls.client.sslmode}
+      client_tls_key_file = ${cfg.tls.client.keyFile}
+      client_tls_cert_file = ${cfg.tls.client.certFile}
+      client_tls_ca_file = ${cfg.tls.client.caFile}
+      ''}
+      ${optionalString (cfg.tls.server != null) ''
+      server_tls_sslmode = ${cfg.tls.server.sslmode}
+      server_tls_key_file = ${cfg.tls.server.keyFile}
+      server_tls_cert_file = ${cfg.tls.server.certFile}
+      server_tls_ca_file = ${cfg.tls.server.caFile}
+      ''}
+
+      # log
+      ${optionalString (cfg.logFile != null) "logfile = ${cfg.homeDir}/${cfg.logFile}"}
+      ${optionalString (cfg.syslog != null) ''
+      syslog = ${if cfg.syslog.enable then "1" else "0"}
+      syslog_ident = ${cfg.syslog.syslogIdent}
+      syslog_facility = ${cfg.syslog.syslogFacility}
+      ''}
+      ${optionalString (cfg.verbose != null) "verbose = ${toString cfg.verbose}"}
+
+      # console access
+      ${optionalString (cfg.adminUsers != null) "admin_users = ${cfg.adminUsers}"}
+      ${optionalString (cfg.statsUsers != null) "stats_users = ${cfg.statsUsers}"}
+
+      # linux
+      pidfile = /run/pgbouncer/pgbouncer.pid
+
+      # extra
+      ${cfg.extraConfig}
+    '';
+  };
+
+in {
+
+  options.services.pgbouncer = {
+
+    # NixOS settings
+
+    enable = mkEnableOption (lib.mdDoc "PostgreSQL connection pooler");
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.pgbouncer;
+      defaultText = literalExpression "pkgs.pgbouncer";
+      description = lib.mdDoc ''
+        The pgbouncer package to use.
+      '';
+    };
+
+    openFirewall = mkOption {
+      type = types.bool;
+      default = false;
+      description = lib.mdDoc ''
+        Whether to automatically open the specified TCP port in the firewall.
+      '';
+    };
+
+    # Generic settings
+
+    logFile = mkOption {
+      type = types.nullOr types.str;
+      default = "pgbouncer.log";
+      description = lib.mdDoc ''
+        Specifies the log file.
+        Either this or syslog has to be specified.
+      '';
+    };
+
+    listenAddress = mkOption {
+      type = types.nullOr types.commas;
+      example = "*";
+      default = null;
+      description = lib.mdDoc ''
+        Specifies a list (comma-separated) of addresses where to listen for TCP connections.
+        You may also use * meaning “listen on all addresses”.
+        When not set, only Unix socket connections are accepted.
+
+        Addresses can be specified numerically (IPv4/IPv6) or by name.
+      '';
+    };
+
+    listenPort = mkOption {
+      type = types.port;
+      default = 6432;
+      description = lib.mdDoc ''
+        Which port to listen on. Applies to both TCP and Unix sockets.
+      '';
+    };
+
+    poolMode = mkOption {
+      type = types.enum [ "session" "transaction" "statement" ];
+      default = "session";
+      description = lib.mdDoc ''
+        Specifies when a server connection can be reused by other clients.
+
+        session
+            Server is released back to pool after client disconnects. Default.
+        transaction
+            Server is released back to pool after transaction finishes.
+        statement
+            Server is released back to pool after query finishes.
+            Transactions spanning multiple statements are disallowed in this mode.
+      '';
+    };
+
+    maxClientConn = mkOption {
+      type = types.int;
+      default = 100;
+      description = lib.mdDoc ''
+        Maximum number of client connections allowed.
+
+        When this setting is increased, then the file descriptor limits in the operating system
+        might also have to be increased. Note that the number of file descriptors potentially
+        used is more than maxClientConn. If each user connects under its own user name to the server,
+        the theoretical maximum used is:
+        maxClientConn + (max pool_size * total databases * total users)
+
+        If a database user is specified in the connection string (all users connect under the same user name),
+        the theoretical maximum is:
+        maxClientConn + (max pool_size * total databases)
+
+        The theoretical maximum should never be reached, unless somebody deliberately crafts a special load for it.
+        Still, it means you should set the number of file descriptors to a safely high number.
+      '';
+    };
+
+    defaultPoolSize = mkOption {
+      type = types.int;
+      default = 20;
+      description = lib.mdDoc ''
+        How many server connections to allow per user/database pair.
+        Can be overridden in the per-database configuration.
+      '';
+    };
+
+    maxDbConnections = mkOption {
+      type = types.int;
+      default = 0;
+      description = lib.mdDoc ''
+        Do not allow more than this many server connections per database (regardless of user).
+        This considers the PgBouncer database that the client has connected to,
+        not the PostgreSQL database of the outgoing connection.
+
+        This can also be set per database in the [databases] section.
+
+        Note that when you hit the limit, closing a client connection to one pool will
+        not immediately allow a server connection to be established for another pool,
+        because the server connection for the first pool is still open.
+        Once the server connection closes (due to idle timeout),
+        a new server connection will immediately be opened for the waiting pool.
+
+        0 = unlimited
+      '';
+    };
+
+    maxUserConnections = mkOption {
+      type = types.int;
+      default = 0;
+      description = lib.mdDoc ''
+        Do not allow more than this many server connections per user (regardless of database).
+        This considers the PgBouncer user that is associated with a pool,
+        which is either the user specified for the server connection
+        or in absence of that the user the client has connected as.
+
+        This can also be set per user in the [users] section.
+
+        Note that when you hit the limit, closing a client connection to one pool
+        will not immediately allow a server connection to be established for another pool,
+        because the server connection for the first pool is still open.
+        Once the server connection closes (due to idle timeout), a new server connection
+        will immediately be opened for the waiting pool.
+
+        0 = unlimited
+      '';
+    };
+
+    ignoreStartupParameters = mkOption {
+      type = types.nullOr types.commas;
+      example = "extra_float_digits";
+      default = null;
+      description = lib.mdDoc ''
+        By default, PgBouncer allows only parameters it can keep track of in startup packets:
+        client_encoding, datestyle, timezone and standard_conforming_strings.
+
+        All others parameters will raise an error.
+        To allow others parameters, they can be specified here, so that PgBouncer knows that
+        they are handled by the admin and it can ignore them.
+
+        If you need to specify multiple values, use a comma-separated list.
+
+        IMPORTANT: When using prometheus-pgbouncer-exporter, you need:
+        extra_float_digits
+        <https://github.com/prometheus-community/pgbouncer_exporter#pgbouncer-configuration>
+      '';
+    };
+
+    # Section [databases]
+    databases = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = {
+        exampledb = "host=/run/postgresql/ port=5432 auth_user=exampleuser dbname=exampledb sslmode=require";
+        bardb = "host=localhost dbname=bazdb";
+        foodb  = "host=host1.example.com port=5432";
+      };
+      description = lib.mdDoc ''
+        Detailed information about PostgreSQL database definitions:
+        <https://www.pgbouncer.org/config.html#section-databases>
+      '';
+    };
+
+    # Section [users]
+    users = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = {
+        user1 = "pool_mode=session";
+      };
+      description = lib.mdDoc ''
+        Optional.
+
+        Detailed information about PostgreSQL user definitions:
+        <https://www.pgbouncer.org/config.html#section-users>
+      '';
+    };
+
+    # Section [peers]
+    peers = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = {
+        "1" = "host=host1.example.com";
+        "2" = "host=/tmp/pgbouncer-2 port=5555";
+      };
+      description = lib.mdDoc ''
+        Optional.
+
+        Detailed information about PostgreSQL database definitions:
+        <https://www.pgbouncer.org/config.html#section-peers>
+      '';
+    };
+
+    # Authentication settings
+    authType = mkOption {
+      type = types.enum [ "cert" "md5" "scram-sha-256" "plain" "trust" "any" "hba" "pam" ];
+      default = "md5";
+      description = lib.mdDoc ''
+        How to authenticate users.
+
+        cert
+            Client must connect over TLS connection with a valid client certificate.
+            The user name is then taken from the CommonName field from the certificate.
+        md5
+            Use MD5-based password check. This is the default authentication method.
+            authFile may contain both MD5-encrypted and plain-text passwords.
+            If md5 is configured and a user has a SCRAM secret, then SCRAM authentication is used automatically instead.
+        scram-sha-256
+            Use password check with SCRAM-SHA-256. authFile has to contain SCRAM secrets or plain-text passwords.
+        plain
+            The clear-text password is sent over the wire. Deprecated.
+        trust
+            No authentication is done. The user name must still exist in authFile.
+        any
+            Like the trust method, but the user name given is ignored.
+            Requires that all databases are configured to log in as a specific user.
+            Additionally, the console database allows any user to log in as admin.
+        hba
+            The actual authentication type is loaded from authHbaFile.
+            This allows different authentication methods for different access paths,
+            for example: connections over Unix socket use the peer auth method, connections over TCP must use TLS.
+        pam
+            PAM is used to authenticate users, authFile is ignored.
+            This method is not compatible with databases using the authUser option.
+            The service name reported to PAM is “pgbouncer”. pam is not supported in the HBA configuration file.
+      '';
+    };
+
+    authHbaFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      example = "/secrets/pgbouncer_hba";
+      description = lib.mdDoc ''
+        HBA configuration file to use when authType is hba.
+
+        See HBA file format details:
+        <https://www.pgbouncer.org/config.html#hba-file-format>
+      '';
+    };
+
+    authFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      example = "/secrets/pgbouncer_authfile";
+      description = lib.mdDoc ''
+        The name of the file to load user names and passwords from.
+
+        See section Authentication file format details:
+        <https://www.pgbouncer.org/config.html#authentication-file-format>
+
+        Most authentication types require that either authFile or authUser be set;
+        otherwise there would be no users defined.
+      '';
+    };
+
+    authUser = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "pgbouncer";
+      description = lib.mdDoc ''
+        If authUser is set, then any user not specified in authFile will be queried
+        through the authQuery query from pg_shadow in the database, using authUser.
+        The password of authUser will be taken from authFile.
+        (If the authUser does not require a password then it does not need to be defined in authFile.)
+
+        Direct access to pg_shadow requires admin rights.
+        It's preferable to use a non-superuser that calls a SECURITY DEFINER function instead.
+      '';
+    };
+
+    authQuery = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "SELECT usename, passwd FROM pg_shadow WHERE usename=$1";
+      description = lib.mdDoc ''
+        Query to load user's password from database.
+
+        Direct access to pg_shadow requires admin rights.
+        It's preferable to use a non-superuser that calls a SECURITY DEFINER function instead.
+
+        Note that the query is run inside the target database.
+        So if a function is used, it needs to be installed into each database.
+      '';
+    };
+
+    authDbname = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "authdb";
+      description = lib.mdDoc ''
+        Database name in the [database] section to be used for authentication purposes.
+        This option can be either global or overriden in the connection string if this parameter is specified.
+      '';
+    };
+
+    # TLS settings
+    tls.client = mkOption {
+      type = types.nullOr (types.submodule {
+        options = {
+          sslmode = mkOption {
+            type = types.enum [ "disable" "allow" "prefer" "require" "verify-ca" "verify-full" ];
+            default = "disable";
+            description = lib.mdDoc ''
+              TLS mode to use for connections from clients.
+              TLS connections are disabled by default.
+
+              When enabled, tls.client.keyFile and tls.client.certFile
+              must be also configured to set up the key and certificate
+              PgBouncer uses to accept client connections.
+
+              disable
+                  Plain TCP. If client requests TLS, it's ignored. Default.
+              allow
+                  If client requests TLS, it is used. If not, plain TCP is used.
+                  If the client presents a client certificate, it is not validated.
+              prefer
+                  Same as allow.
+              require
+                  Client must use TLS. If not, the client connection is rejected.
+                  If the client presents a client certificate, it is not validated.
+              verify-ca
+                  Client must use TLS with valid client certificate.
+              verify-full
+                  Same as verify-ca
+            '';
+          };
+          certFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer.key";
+            description = lib.mdDoc "Path to certificate for private key. Clients can validate it";
+          };
+          keyFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer.crt";
+            description = lib.mdDoc "Path to private key for PgBouncer to accept client connections";
+          };
+          caFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer.crt";
+            description = lib.mdDoc "Path to root certificate file to validate client certificates";
+          };
+        };
+      });
+      default = null;
+      description = lib.mdDoc ''
+        <https://www.pgbouncer.org/config.html#tls-settings>
+      '';
+    };
+
+    tls.server = mkOption {
+      type = types.nullOr (types.submodule {
+        options = {
+          sslmode = mkOption {
+            type = types.enum [ "disable" "allow" "prefer" "require" "verify-ca" "verify-full" ];
+            default = "disable";
+            description = lib.mdDoc ''
+              TLS mode to use for connections to PostgreSQL servers.
+              TLS connections are disabled by default.
+
+              disable
+                  Plain TCP. TLS is not even requested from the server. Default.
+              allow
+                  FIXME: if server rejects plain, try TLS?
+              prefer
+                  TLS connection is always requested first from PostgreSQL.
+                  If refused, the connection will be established over plain TCP.
+                  Server certificate is not validated.
+              require
+                  Connection must go over TLS. If server rejects it, plain TCP is not attempted.
+                  Server certificate is not validated.
+              verify-ca
+                  Connection must go over TLS and server certificate must be valid according to tls.server.caFile.
+                  Server host name is not checked against certificate.
+              verify-full
+                  Connection must go over TLS and server certificate must be valid according to tls.server.caFile.
+                  Server host name must match certificate information.
+            '';
+          };
+          certFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer_server.key";
+            description = lib.mdDoc "Certificate for private key. PostgreSQL server can validate it.";
+          };
+          keyFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer_server.crt";
+            description = lib.mdDoc "Private key for PgBouncer to authenticate against PostgreSQL server.";
+          };
+          caFile = mkOption {
+            type = types.path;
+            example = "/secrets/pgbouncer_server.crt";
+            description = lib.mdDoc "Root certificate file to validate PostgreSQL server certificates.";
+          };
+        };
+      });
+      default = null;
+      description = lib.mdDoc ''
+        <https://www.pgbouncer.org/config.html#tls-settings>
+      '';
+    };
+
+    # Log settings
+    syslog = mkOption {
+      type = types.nullOr (types.submodule {
+        options = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = lib.mdDoc ''
+              Toggles syslog on/off.
+            '';
+          };
+          syslogIdent = mkOption {
+            type = types.str;
+            default = "pgbouncer";
+            description = lib.mdDoc ''
+              Under what name to send logs to syslog.
+            '';
+          };
+          syslogFacility = mkOption {
+            type = types.enum [ "auth" "authpriv" "daemon" "user" "local0" "local1" "local2" "local3" "local4" "local5" "local6" "local7" ];
+            default = "daemon";
+            description = lib.mdDoc ''
+              Under what facility to send logs to syslog.
+            '';
+          };
+        };
+      });
+      default = null;
+      description = lib.mdDoc ''
+        <https://www.pgbouncer.org/config.html#log-settings>
+      '';
+    };
+
+    verbose = lib.mkOption {
+      type = lib.types.int;
+      default = 0;
+      description = lib.mdDoc ''
+        Increase verbosity. Mirrors the “-v” switch on the command line.
+      '';
+    };
+
+    # Console access control
+    adminUsers = mkOption {
+      type = types.nullOr types.commas;
+      default = null;
+      description = lib.mdDoc ''
+        Comma-separated list of database users that are allowed to connect and run all commands on the console.
+        Ignored when authType is any, in which case any user name is allowed in as admin.
+      '';
+    };
+
+    statsUsers = mkOption {
+      type = types.nullOr types.commas;
+      default = null;
+      description = lib.mdDoc ''
+        Comma-separated list of database users that are allowed to connect and run read-only queries on the console.
+        That means all SHOW commands except SHOW FDS.
+      '';
+    };
+
+    # Linux settings
+    openFilesLimit = lib.mkOption {
+      type = lib.types.int;
+      default = 65536;
+      description = lib.mdDoc ''
+        Maximum number of open files.
+      '';
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = "pgbouncer";
+      description = lib.mdDoc ''
+        The user pgbouncer is run as.
+      '';
+    };
+
+    group = mkOption {
+      type = types.str;
+      default = "pgbouncer";
+      description = lib.mdDoc ''
+        The group pgbouncer is run as.
+      '';
+    };
+
+    homeDir = mkOption {
+      type = types.path;
+      default = "/var/lib/pgbouncer";
+      description = lib.mdDoc ''
+        Specifies the home directory.
+      '';
+    };
+
+    # Extra settings
+    extraConfig = mkOption {
+      type = types.lines;
+      description = lib.mdDoc ''
+        Any additional text to be appended to config.ini
+         <https://www.pgbouncer.org/config.html>.
+      '';
+      default = "";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.groups.${cfg.group} = { };
+    users.users.${cfg.user} = {
+      description = "PgBouncer service user";
+      group = cfg.group;
+      home = cfg.homeDir;
+      createHome = true;
+      isSystemUser = true;
+    };
+
+    systemd.services.pgbouncer = {
+      description = "PgBouncer - PostgreSQL connection pooler";
+      wants    = [ "postgresql.service" ];
+      after    = [ "postgresql.service" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "forking";
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = "${pkgs.pgbouncer}/bin/pgbouncer -d ${confFile}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
+        RuntimeDirectory = "pgbouncer";
+        PIDFile = "/run/pgbouncer/pgbouncer.pid";
+        LimitNOFILE = cfg.openFilesLimit;
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
+
+  };
+
+    meta.maintainers = [ maintainers._1000101 ];
+
+}
diff --git a/nixos/modules/services/misc/cgminer.nix b/nixos/modules/services/misc/cgminer.nix
index fced106cb3259..a6fbfee73bad3 100644
--- a/nixos/modules/services/misc/cgminer.nix
+++ b/nixos/modules/services/misc/cgminer.nix
@@ -11,7 +11,7 @@ let
     mapAttrsToList (n: v: ''"${n}": "${(concatStringsSep "," (map convType v))}"'')
       (foldAttrs (n: a: [n] ++ a) [] cfg.hardware);
   mergedConfig = with builtins;
-    mapAttrsToList (n: v: ''"${n}":  ${if isBool v then "" else ''"''}${convType v}${if isBool v then "" else ''"''}'')
+    mapAttrsToList (n: v: ''"${n}":  ${if isBool v then convType v else ''"${convType v}"''}'')
       cfg.config;
 
   cgminerConfig = pkgs.writeText "cgminer.conf" ''
diff --git a/nixos/modules/services/misc/sourcehut/default.nix b/nixos/modules/services/misc/sourcehut/default.nix
index d4391bc49e315..580a009a0ad39 100644
--- a/nixos/modules/services/misc/sourcehut/default.nix
+++ b/nixos/modules/services/misc/sourcehut/default.nix
@@ -8,13 +8,13 @@ let
   settingsFormat = pkgs.formats.ini {
     listToValue = concatMapStringsSep "," (generators.mkValueStringDefault {});
     mkKeyValue = k: v:
-      if v == null then ""
-      else generators.mkKeyValueDefault {
+      optionalString (v != null)
+      (generators.mkKeyValueDefault {
         mkValueString = v:
           if v == true then "yes"
           else if v == false then "no"
           else generators.mkValueStringDefault {} v;
-      } "=" k v;
+      } "=" k v);
   };
   configIniOfService = srv: settingsFormat.generate "sourcehut-${srv}-config.ini"
     # Each service needs access to only a subset of sections (and secrets).
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
index e02acad3ecd1d..f95412efd7dd3 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
@@ -104,12 +104,12 @@ in
       LoadCredential = "configFile:${computedConfigFile}";
       ExecStart = ''
         ${cfg.package}/bin/pve_exporter \
-          --${if cfg.collectors.status == true then "" else "no-"}collector.status \
-          --${if cfg.collectors.version == true then "" else "no-"}collector.version \
-          --${if cfg.collectors.node == true then "" else "no-"}collector.node \
-          --${if cfg.collectors.cluster == true then "" else "no-"}collector.cluster \
-          --${if cfg.collectors.resources == true then "" else "no-"}collector.resources \
-          --${if cfg.collectors.config == true then "" else "no-"}collector.config \
+          --${optionalString (!cfg.collectors.status) "no-"}collector.status \
+          --${optionalString (!cfg.collectors.version) "no-"}collector.version \
+          --${optionalString (!cfg.collectors.node) "no-"}collector.node \
+          --${optionalString (!cfg.collectors.cluster) "no-"}collector.cluster \
+          --${optionalString (!cfg.collectors.resources) "no-"}collector.resources \
+          --${optionalString (!cfg.collectors.config) "no-"}collector.config \
           %d/configFile \
           ${toString cfg.port} ${cfg.listenAddress}
       '';
diff --git a/nixos/modules/services/networking/biboumi.nix b/nixos/modules/services/networking/biboumi.nix
index 1428856764e65..d44a46b35a29c 100644
--- a/nixos/modules/services/networking/biboumi.nix
+++ b/nixos/modules/services/networking/biboumi.nix
@@ -8,8 +8,7 @@ let
   settingsFile = pkgs.writeText "biboumi.cfg" (
     generators.toKeyValue {
       mkKeyValue = k: v:
-        if v == null then ""
-        else generators.mkKeyValueDefault {} "=" k v;
+        lib.optionalString (v != null) (generators.mkKeyValueDefault {} "=" k v);
     } cfg.settings);
   need_CAP_NET_BIND_SERVICE = cfg.settings.identd_port != 0 && cfg.settings.identd_port < 1024;
 in
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 5a19475161fdf..80085da92702c 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -239,7 +239,7 @@ in
       after = [ "network-online.target" ];
       bindsTo = [ "network-online.target" ];
 
-      preStart = if cfg.confFile != null then "" else ''
+      preStart = optionalString (cfg.confFile == null) ''
         [ -e /etc/cjdns.keys ] && source /etc/cjdns.keys
 
         if [ -z "$CJDNS_PRIVATE_KEY" ]; then
diff --git a/nixos/modules/services/networking/libreswan.nix b/nixos/modules/services/networking/libreswan.nix
index 785729d8f742c..db4d2f7f0ba00 100644
--- a/nixos/modules/services/networking/libreswan.nix
+++ b/nixos/modules/services/networking/libreswan.nix
@@ -14,8 +14,8 @@ let
     nonchars = filter (x : !(elem x.value chars))
                (imap0 (i: v: {ind = i; value = v;}) (stringToCharacters str));
   in
-    if length nonchars == 0 then ""
-    else substring (head nonchars).ind (add 1 (sub (last nonchars).ind (head nonchars).ind)) str;
+    lib.optionalString (nonchars != [ ])
+      (substring (head nonchars).ind (add 1 (sub (last nonchars).ind (head nonchars).ind)) str);
   indent = str: concatStrings (concatMap (s: ["  " (trim [" " "\t"] s) "\n"]) (splitString "\n" str));
   configText = indent (toString cfg.configSetup);
   connectionText = concatStrings (mapAttrsToList (n: v:
diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix
index ebade7aa8e403..37a1ff8b2d347 100644
--- a/nixos/modules/services/networking/murmur.nix
+++ b/nixos/modules/services/networking/murmur.nix
@@ -19,8 +19,8 @@ let
     welcometext="${cfg.welcometext}"
     port=${toString cfg.port}
 
-    ${if cfg.hostName == "" then "" else "host="+cfg.hostName}
-    ${if cfg.password == "" then "" else "serverpassword="+cfg.password}
+    ${optionalString (cfg.hostName != "") "host=${cfg.hostName}"}
+    ${optionalString (cfg.password != "") "serverpassword=${cfg.password}"}
 
     bandwidth=${toString cfg.bandwidth}
     users=${toString cfg.users}
@@ -32,17 +32,17 @@ let
     bonjour=${boolToString cfg.bonjour}
     sendversion=${boolToString cfg.sendVersion}
 
-    ${if cfg.registerName     == "" then "" else "registerName="+cfg.registerName}
-    ${if cfg.registerPassword == "" then "" else "registerPassword="+cfg.registerPassword}
-    ${if cfg.registerUrl      == "" then "" else "registerUrl="+cfg.registerUrl}
-    ${if cfg.registerHostname == "" then "" else "registerHostname="+cfg.registerHostname}
+    ${optionalString (cfg.registerName != "") "registerName=${cfg.registerName}"}
+    ${optionalString (cfg.registerPassword == "") "registerPassword=${cfg.registerPassword}"}
+    ${optionalString (cfg.registerUrl != "") "registerUrl=${cfg.registerUrl}"}
+    ${optionalString (cfg.registerHostname != "") "registerHostname=${cfg.registerHostname}"}
 
     certrequired=${boolToString cfg.clientCertRequired}
-    ${if cfg.sslCert == "" then "" else "sslCert="+cfg.sslCert}
-    ${if cfg.sslKey  == "" then "" else "sslKey="+cfg.sslKey}
-    ${if cfg.sslCa   == "" then "" else "sslCA="+cfg.sslCa}
+    ${optionalString (cfg.sslCert != "") "sslCert=${cfg.sslCert}"}
+    ${optionalString (cfg.sslKey != "") "sslKey=${cfg.sslKey}"}
+    ${optionalString (cfg.sslCa != "") "sslCA=${cfg.sslCa}"}
 
-    ${lib.optionalString (cfg.dbus != null) "dbus=${cfg.dbus}"}
+    ${optionalString (cfg.dbus != null) "dbus=${cfg.dbus}"}
 
     ${cfg.extraConfig}
   '';
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 09f3bdc7ae07d..6db728e7aa5ae 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -137,8 +137,8 @@ let
   '';
 
   yesOrNo = b: if b then "yes" else "no";
-  maybeString = prefix: x: if x == null then "" else ''${prefix} "${x}"'';
-  maybeToString = prefix: x: if x == null then "" else ''${prefix} ${toString x}'';
+  maybeString = prefix: x: optionalString (x != null) ''${prefix} "${x}"'';
+  maybeToString = prefix: x: optionalString (x != null) ''${prefix} ${toString x}'';
   forEach = pre: l: concatMapStrings (x: pre + x + "\n") l;
 
 
diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix
index af64969c2fcd4..129e420555143 100644
--- a/nixos/modules/services/networking/ssh/lshd.nix
+++ b/nixos/modules/services/networking/ssh/lshd.nix
@@ -165,9 +165,7 @@ in
         ${lsh}/sbin/lshd --daemonic \
           --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
           -p ${toString portNumber} \
-          ${if interfaces == [] then ""
-            else (concatStrings (map (i: "--interface=\"${i}\"")
-                                     interfaces))} \
+          ${optionalString (interfaces != []) (concatStrings (map (i: "--interface=\"${i}\"") interfaces))} \
           -h "${hostKey}" \
           ${optionalString (!syslog) "--no-syslog" } \
           ${if passwordAuthentication then "--password" else "--no-password" } \
diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix
index f1d2f462a7554..47bd358f979da 100644
--- a/nixos/modules/services/scheduling/fcron.nix
+++ b/nixos/modules/services/scheduling/fcron.nix
@@ -6,7 +6,7 @@ let
 
   cfg = config.services.fcron;
 
-  queuelen = if cfg.queuelen == null then "" else "-q ${toString cfg.queuelen}";
+  queuelen = optionalString (cfg.queuelen != null) "-q ${toString cfg.queuelen}";
 
   # Duplicate code, also found in cron.nix. Needs deduplication.
   systemCronJobs =
diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix
index e875be47fb918..8823da0100141 100644
--- a/nixos/modules/services/web-apps/invidious.nix
+++ b/nixos/modules/services/web-apps/invidious.nix
@@ -62,7 +62,7 @@ let
         port = cfg.database.port;
         # Blank for unix sockets, see
         # https://github.com/will/crystal-pg/blob/1548bb255210/src/pq/conninfo.cr#L100-L108
-        host = if cfg.database.host == null then "" else cfg.database.host;
+        host = lib.optionalString (cfg.database.host != null) cfg.database.host;
         # Not needed because peer authentication is enabled
         password = lib.mkIf (cfg.database.host == null) "";
       };
diff --git a/nixos/modules/services/web-apps/invoiceplane.nix b/nixos/modules/services/web-apps/invoiceplane.nix
index 8be1fd3055d09..f419b75cf70fe 100644
--- a/nixos/modules/services/web-apps/invoiceplane.nix
+++ b/nixos/modules/services/web-apps/invoiceplane.nix
@@ -16,7 +16,7 @@ let
     DB_HOSTNAME=${cfg.database.host}
     DB_USERNAME=${cfg.database.user}
     # NOTE: file_get_contents adds newline at the end of returned string
-    DB_PASSWORD=${if cfg.database.passwordFile == null then "" else "trim(file_get_contents('${cfg.database.passwordFile}'), \"\\r\\n\")"}
+    DB_PASSWORD=${optionalString (cfg.database.passwordFile != null) "trim(file_get_contents('${cfg.database.passwordFile}'), \"\\r\\n\")"}
     DB_DATABASE=${cfg.database.name}
     DB_PORT=${toString cfg.database.port}
     SESS_EXPIRATION=864000
diff --git a/nixos/modules/services/web-apps/peertube.nix b/nixos/modules/services/web-apps/peertube.nix
index 4826b2cab6a32..17e170c33deea 100644
--- a/nixos/modules/services/web-apps/peertube.nix
+++ b/nixos/modules/services/web-apps/peertube.nix
@@ -348,7 +348,7 @@ in {
         };
         redis = {
           hostname = "${toString cfg.redis.host}";
-          port = (if cfg.redis.port == null then "" else cfg.redis.port);
+          port = (lib.optionalString (cfg.redis.port != null) cfg.redis.port);
         };
         storage = {
           tmp = lib.mkDefault "/var/lib/peertube/storage/tmp/";
diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix
index 5042fbf1f8f29..e9f42c41183b1 100644
--- a/nixos/modules/services/web-servers/lighttpd/cgit.nix
+++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
   cfg = config.services.lighttpd.cgit;
-  pathPrefix = if stringLength cfg.subdir == 0 then "" else "/" + cfg.subdir;
+  pathPrefix = optionalString (stringLength cfg.subdir != 0) ("/" + cfg.subdir);
   configFile = pkgs.writeText "cgitrc"
     ''
       # default paths to static assets
diff --git a/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix
index 3cfa6e044b73d..e4cd9fd99e40c 100644
--- a/nixos/modules/services/x11/desktop-managers/phosh.nix
+++ b/nixos/modules/services/x11/desktop-managers/phosh.nix
@@ -100,7 +100,7 @@ let
     };
   };
 
-  optionalKV = k: v: if v == null then "" else "${k} = ${builtins.toString v}";
+  optionalKV = k: v: optionalString (v != null) "${k} = ${builtins.toString v}";
 
   renderPhocOutput = name: output: let
     modelines = if builtins.isList output.modeline
diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix
index 31e9ec626ca64..e618070f0dc3e 100644
--- a/nixos/modules/system/boot/kernel_config.nix
+++ b/nixos/modules/system/boot/kernel_config.nix
@@ -70,11 +70,10 @@ let
       let
         val = if item.freeform != null then item.freeform else item.tristate;
       in
-        if val == null
-          then ""
-          else if (item.optional)
+        optionalString (val != null)
+            (if (item.optional)
             then "${key}? ${mkValue val}\n"
-            else "${key} ${mkValue val}\n";
+            else "${key} ${mkValue val}\n");
 
     mkConf = cfg: concatStrings (mapAttrsToList mkConfigLine cfg);
   in mkConf exprs;
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index b57e343d2ac2e..66b54155fbfbc 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -65,8 +65,8 @@ let
         [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ]
         ++ optional cfg.efiSupport efibootmgr
         ++ optionals cfg.useOSProber [ busybox os-prober ]);
-      font = if cfg.font == null then ""
-        else (if lib.last (lib.splitString "." cfg.font) == "pf2"
+      font = lib.optionalString (cfg.font != null) (
+             if lib.last (lib.splitString "." cfg.font) == "pf2"
              then cfg.font
              else "${convertedFont}");
     });
diff --git a/nixos/modules/system/boot/systemd/user.nix b/nixos/modules/system/boot/systemd/user.nix
index 92e1b087392dd..1b6398d2f929e 100644
--- a/nixos/modules/system/boot/systemd/user.nix
+++ b/nixos/modules/system/boot/systemd/user.nix
@@ -42,7 +42,7 @@ let
 
   writeTmpfiles = { rules, user ? null }:
     let
-      suffix = if user == null then "" else "-${user}";
+      suffix = optionalString (user != null) "-${user}";
     in
     pkgs.writeTextFile {
       name = "nixos-user-tmpfiles.d${suffix}";
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 80cf5cd3771b0..66d7d064291b0 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -599,6 +599,7 @@ in {
   peertube = handleTestOn ["x86_64-linux"] ./web-apps/peertube.nix {};
   peroxide = handleTest ./peroxide.nix {};
   pgadmin4 = handleTest ./pgadmin4.nix {};
+  pgbouncer = handleTest ./pgbouncer.nix {};
   pgjwt = handleTest ./pgjwt.nix {};
   pgmanage = handleTest ./pgmanage.nix {};
   phosh = handleTest ./phosh.nix {};
diff --git a/nixos/tests/pgbouncer.nix b/nixos/tests/pgbouncer.nix
new file mode 100644
index 0000000000000..1e72327d42005
--- /dev/null
+++ b/nixos/tests/pgbouncer.nix
@@ -0,0 +1,61 @@
+import ./make-test-python.nix ({ pkgs, ... } :
+let
+  testAuthFile = pkgs.writeTextFile {
+    name = "authFile";
+    text = ''
+      "testuser" "testpass"
+    '';
+  };
+in
+{
+  name = "pgbouncer";
+  meta = with pkgs.lib.maintainers; {
+    maintainers = [ _1000101 ];
+  };
+  nodes = {
+    one = { config, pkgs, ... }: {
+
+      systemd.services.postgresql = {
+        postStart = ''
+            ${pkgs.postgresql}/bin/psql -U postgres -c "ALTER ROLE testuser WITH LOGIN PASSWORD 'testpass'";
+        '';
+      };
+
+      services = {
+        postgresql = {
+          enable = true;
+          ensureDatabases = [ "testdb" ];
+          ensureUsers = [
+          {
+            name = "testuser";
+            ensurePermissions = {
+              "DATABASE testdb" = "ALL PRIVILEGES";
+            };
+          }];
+          authentication = ''
+            local testdb testuser scram-sha-256
+          '';
+        };
+
+        pgbouncer = {
+          enable = true;
+          listenAddress = "localhost";
+          databases = { testdb = "host=/run/postgresql/ port=5432 auth_user=testuser dbname=testdb"; };
+          authType = "scram-sha-256";
+          authFile = testAuthFile;
+        };
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+    one.wait_for_unit("default.target")
+    one.require_unit_state("pgbouncer.service", "active")
+
+    # Test if we can make a query through PgBouncer
+    one.wait_until_succeeds(
+        "psql 'postgres://testuser:testpass@localhost:6432/testdb' -c 'SELECT 1;'"
+    )
+  '';
+})
diff --git a/pkgs/applications/editors/texmacs/darwin.nix b/pkgs/applications/editors/texmacs/darwin.nix
index ff090dd3259a5..8c74d8c5c8f24 100644
--- a/pkgs/applications/editors/texmacs/darwin.nix
+++ b/pkgs/applications/editors/texmacs/darwin.nix
@@ -47,10 +47,10 @@ stdenv.mkDerivation {
 
   postInstall = "wrapProgram $out/Applications/TeXmacs-${version}/Contents/MacOS/TeXmacs --suffix PATH : " +
     "${ghostscript}/bin:" +
-    (if aspell == null then "" else "${aspell}/bin:") +
-    (if tex == null then "" else "${tex}/bin:") +
-    (if netpbm == null then "" else "${lib.getBin netpbm}/bin:") +
-    (if imagemagick == null then "" else "${imagemagick}/bin:");
+    (lib.optionalString (aspell != null) "${aspell}/bin:") +
+    (lib.optionalString (tex != null) "${tex}/bin:") +
+    (lib.optionalString (netpbm != null) "${lib.getBin netpbm}/bin:") +
+    (lib.optionalString (imagemagick != null) "${imagemagick}/bin:");
 
   enableParallelBuilding = true;
 
diff --git a/pkgs/applications/editors/vscode/vscodium.nix b/pkgs/applications/editors/vscode/vscodium.nix
index dabd413632dba..bab8de8b594a7 100644
--- a/pkgs/applications/editors/vscode/vscodium.nix
+++ b/pkgs/applications/editors/vscode/vscodium.nix
@@ -22,7 +22,7 @@ let
     armv7l-linux = "1cp739i5002j2kmdh3rhh7p88gyvjrfwcr430g5dvhdp7mgkbwn1";
   }.${system} or throwSystem;
 
-  sourceRoot = if stdenv.isDarwin then "" else ".";
+  sourceRoot = lib.optionalString (!stdenv.isDarwin) ".";
 in
   callPackage ./generic.nix rec {
     inherit sourceRoot commandLineArgs useVSCodeRipgrep;
diff --git a/pkgs/applications/misc/mkgmap/default.nix b/pkgs/applications/misc/mkgmap/default.nix
index 45fe2e1395bca..390bc01413379 100644
--- a/pkgs/applications/misc/mkgmap/default.nix
+++ b/pkgs/applications/misc/mkgmap/default.nix
@@ -15,12 +15,12 @@ let
 in
 stdenv.mkDerivation rec {
   pname = "mkgmap";
-  version = "4909";
+  version = "4910";
 
   src = fetchsvn {
     url = "https://svn.mkgmap.org.uk/mkgmap/mkgmap/trunk";
     rev = version;
-    sha256 = "sha256-B3G1xpDZtJqkjyufLwYnJQlXREvN6OrJEjHWWP05jDM=";
+    sha256 = "sha256-t4SyvDvwNdqKh95MRmHxlX6q84dN0y4ANPIXqS7ynBA=";
   };
 
   patches = [
diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix
index 3b4826930ec0f..70b1de5253b81 100644
--- a/pkgs/applications/networking/browsers/chromium/default.nix
+++ b/pkgs/applications/networking/browsers/chromium/default.nix
@@ -135,9 +135,7 @@ let
     };
   };
 
-  suffix = if (channel == "stable" || channel == "ungoogled-chromium")
-    then ""
-    else "-" + channel;
+  suffix = lib.optionalString (channel != "stable" && channel != "ungoogled-chromium") ("-" + channel);
 
   sandboxExecutableName = chromium.browser.passthru.sandboxExecutableName;
 
diff --git a/pkgs/applications/networking/browsers/firefox/common.nix b/pkgs/applications/networking/browsers/firefox/common.nix
index 348c93d0c3835..753e1c9d59ef9 100644
--- a/pkgs/applications/networking/browsers/firefox/common.nix
+++ b/pkgs/applications/networking/browsers/firefox/common.nix
@@ -187,7 +187,6 @@ let
       # These values are exposed through telemetry
       "app.distributor" = "nixos";
       "app.distributor.channel" = "nixpkgs";
-      "app.partner.nixos" = "nixos";
     };
   });
 
diff --git a/pkgs/applications/networking/browsers/microsoft-edge/browser.nix b/pkgs/applications/networking/browsers/microsoft-edge/browser.nix
index 2af28bb8dd068..7f72a42ffe0d0 100644
--- a/pkgs/applications/networking/browsers/microsoft-edge/browser.nix
+++ b/pkgs/applications/networking/browsers/microsoft-edge/browser.nix
@@ -46,13 +46,9 @@ let
              then baseName
              else baseName + "-" + channel;
 
-  iconSuffix = if channel == "stable"
-               then ""
-               else "_${channel}";
+  iconSuffix = lib.optionalString (channel != "stable") "_${channel}";
 
-  desktopSuffix = if channel == "stable"
-                  then ""
-                  else "-${channel}";
+  desktopSuffix = lib.optionalString (channel != "stable") "-${channel}";
 in
 
 stdenv.mkDerivation rec {
diff --git a/pkgs/applications/networking/flexget/default.nix b/pkgs/applications/networking/flexget/default.nix
index 7b2c8c10f4a23..d33a89f0bcc8d 100644
--- a/pkgs/applications/networking/flexget/default.nix
+++ b/pkgs/applications/networking/flexget/default.nix
@@ -6,7 +6,7 @@
 
 python3.pkgs.buildPythonApplication rec {
   pname = "flexget";
-  version = "3.7.9";
+  version = "3.7.10";
   format = "pyproject";
 
   # Fetch from GitHub in order to use `requirements.in`
@@ -14,7 +14,7 @@ python3.pkgs.buildPythonApplication rec {
     owner = "Flexget";
     repo = "Flexget";
     rev = "refs/tags/v${version}";
-    hash = "sha256-TD57tGLTYy8E7lx6hzH1/00oWFYqCQ325UNEhgv/AEA=";
+    hash = "sha256-5wf1oQzriawhthAfHMMtZbUMvGNviBPzmnLKahRkmXQ=";
   };
 
   postPatch = ''
diff --git a/pkgs/applications/office/libreoffice/default.nix b/pkgs/applications/office/libreoffice/default.nix
index 25e8f18998e2e..518167cb33d12 100644
--- a/pkgs/applications/office/libreoffice/default.nix
+++ b/pkgs/applications/office/libreoffice/default.nix
@@ -395,7 +395,7 @@ in
   dontWrapQtApps = true;
 
   configureFlags = [
-    (if withHelp then "" else "--without-help")
+    (lib.optionalString (!withHelp) "--without-help")
     "--with-boost=${getDev boost}"
     "--with-boost-libdir=${getLib boost}/lib"
     "--with-beanshell-jar=${bsh}"
diff --git a/pkgs/applications/office/trilium/desktop.nix b/pkgs/applications/office/trilium/desktop.nix
index 0436c31c94ee8..9e100459f7ae6 100644
--- a/pkgs/applications/office/trilium/desktop.nix
+++ b/pkgs/applications/office/trilium/desktop.nix
@@ -42,6 +42,7 @@ let
         comment = meta.description;
         desktopName = "Trilium Notes";
         categories = [ "Office" ];
+        startupWMClass = "trilium notes";
       })
     ];
 
diff --git a/pkgs/applications/science/logic/hol_light/default.nix b/pkgs/applications/science/logic/hol_light/default.nix
index 4c105a40e20db..9f379252fd529 100644
--- a/pkgs/applications/science/logic/hol_light/default.nix
+++ b/pkgs/applications/science/logic/hol_light/default.nix
@@ -2,8 +2,7 @@
 
 let
   load_num =
-    if num == null then "" else
-    ''
+    lib.optionalString (num != null) ''
       -I ${num}/lib/ocaml/${ocaml.version}/site-lib/num \
       -I ${num}/lib/ocaml/${ocaml.version}/site-lib/top-num \
       -I ${num}/lib/ocaml/${ocaml.version}/site-lib/stublibs \
diff --git a/pkgs/applications/science/math/sage/sage-tests.nix b/pkgs/applications/science/math/sage/sage-tests.nix
index 4910f5e8bf1d2..1a415ae65e96a 100644
--- a/pkgs/applications/science/math/sage/sage-tests.nix
+++ b/pkgs/applications/science/math/sage/sage-tests.nix
@@ -19,7 +19,7 @@ let
   runAllTests = files == null;
   testArgs = if runAllTests then "--all" else testFileList;
   patienceSpecifier = lib.optionalString longTests "--long";
-  timeSpecifier = if timeLimit == null then "" else "--short ${toString timeLimit}";
+  timeSpecifier = lib.optionalString (timeLimit != null) "--short ${toString timeLimit}";
   relpathToArg = relpath: lib.escapeShellArg "${src}/${relpath}"; # paths need to be absolute
   testFileList = lib.concatStringsSep " " (map relpathToArg files);
 in
diff --git a/pkgs/applications/version-management/sapling/default.nix b/pkgs/applications/version-management/sapling/default.nix
index 0d14d512c5f29..796d76cc6ef82 100644
--- a/pkgs/applications/version-management/sapling/default.nix
+++ b/pkgs/applications/version-management/sapling/default.nix
@@ -38,7 +38,7 @@ let
   #
   # See https://github.com/NixOS/nixpkgs/pull/198311#issuecomment-1326894295
   myCargoSetupHook = rustPlatform.cargoSetupHook.overrideAttrs (old: {
-    cargoConfig = if stdenv.isDarwin then "" else old.cargoConfig;
+    cargoConfig = lib.optionalString (!stdenv.isDarwin) old.cargoConfig;
   });
 
   src = fetchFromGitHub {
diff --git a/pkgs/applications/video/obs-studio/plugins/obs-vertical-canvas.nix b/pkgs/applications/video/obs-studio/plugins/obs-vertical-canvas.nix
index 6c8ef3b67a4af..ffea337c329c8 100644
--- a/pkgs/applications/video/obs-studio/plugins/obs-vertical-canvas.nix
+++ b/pkgs/applications/video/obs-studio/plugins/obs-vertical-canvas.nix
@@ -9,13 +9,13 @@
 
 stdenv.mkDerivation rec {
   pname = "obs-vertical-canvas";
-  version = "1.2.4";
+  version = "1.2.5";
 
   src = fetchFromGitHub {
     owner = "Aitum";
     repo = "obs-vertical-canvas";
     rev = version;
-    sha256 = "sha256-a9r01adzeC8KSr+ATgRQLoJ+dlAj6NWFZ5cRYlS7FeM=";
+    sha256 = "sha256-6I73YukhqOLsqVimTfVKYG6LzIYoJRnMaxkPhEAinfQ=";
   };
 
   nativeBuildInputs = [ cmake ];
diff --git a/pkgs/applications/window-managers/sway/wrapper.nix b/pkgs/applications/window-managers/sway/wrapper.nix
index b4e9289f19a53..21a7daa1fa34b 100644
--- a/pkgs/applications/window-managers/sway/wrapper.nix
+++ b/pkgs/applications/window-managers/sway/wrapper.nix
@@ -28,7 +28,7 @@ let
        export DBUS_SESSION_BUS_ADDRESS
        exec ${sway}/bin/sway "$@"
      else
-       exec ${if !dbusSupport then "" else "${dbus}/bin/dbus-run-session"} ${sway}/bin/sway "$@"
+       exec ${lib.optionalString dbusSupport "${dbus}/bin/dbus-run-session"} ${sway}/bin/sway "$@"
      fi
    '';
 in symlinkJoin {
diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix
index adaf80dcd916e..9ed4f5886f617 100644
--- a/pkgs/build-support/bintools-wrapper/default.nix
+++ b/pkgs/build-support/bintools-wrapper/default.nix
@@ -59,12 +59,12 @@ let
   bintoolsVersion = lib.getVersion bintools;
   bintoolsName = lib.removePrefix targetPrefix (lib.getName bintools);
 
-  libc_bin = if libc == null then "" else getBin libc;
-  libc_dev = if libc == null then "" else getDev libc;
-  libc_lib = if libc == null then "" else getLib libc;
-  bintools_bin = if nativeTools then "" else getBin bintools;
+  libc_bin = lib.optionalString (libc != null) (getBin libc);
+  libc_dev = lib.optionalString (libc != null) (getDev libc);
+  libc_lib = lib.optionalString (libc != null) (getLib libc);
+  bintools_bin = lib.optionalString (!nativeTools) (getBin bintools);
   # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
-  coreutils_bin = if nativeTools then "" else getBin coreutils;
+  coreutils_bin = lib.optionalString (!nativeTools) (getBin coreutils);
 
   # See description in cc-wrapper.
   suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
@@ -103,7 +103,7 @@ in
 stdenv.mkDerivation {
   pname = targetPrefix
     + (if name != "" then name else "${bintoolsName}-wrapper");
-  version = if bintools == null then "" else bintoolsVersion;
+  version = lib.optionalString (bintools != null) bintoolsVersion;
 
   preferLocalBuild = true;
 
@@ -265,7 +265,7 @@ stdenv.mkDerivation {
     # install the wrapper, you get tools like objdump (same for any
     # binaries of libc).
     + optionalString (!nativeTools) ''
-      printWords ${bintools_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
+      printWords ${bintools_bin} ${lib.optionalString (libc != null) libc_bin} > $out/nix-support/propagated-user-env-packages
     ''
 
     ##
@@ -381,7 +381,7 @@ stdenv.mkDerivation {
     # for substitution in utils.bash
     expandResponseParams = "${expand-response-params}/bin/expand-response-params";
     shell = getBin shell + shell.shellPath or "";
-    gnugrep_bin = if nativeTools then "" else gnugrep;
+    gnugrep_bin = lib.optionalString (!nativeTools) gnugrep;
     wrapperName = "BINTOOLS_WRAPPER";
     inherit dynamicLinker targetPrefix suffixSalt coreutils_bin;
     inherit bintools_bin libc_bin libc_dev libc_lib;
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index db3efa068c0fd..551074e0a2112 100644
--- a/pkgs/build-support/cc-wrapper/default.nix
+++ b/pkgs/build-support/cc-wrapper/default.nix
@@ -75,14 +75,14 @@ let
   ccVersion = lib.getVersion cc;
   ccName = lib.removePrefix targetPrefix (lib.getName cc);
 
-  libc_bin = if libc == null then "" else getBin libc;
-  libc_dev = if libc == null then "" else getDev libc;
-  libc_lib = if libc == null then "" else getLib libc;
+  libc_bin = optionalString (libc != null) (getBin libc);
+  libc_dev = optionalString (libc != null) (getDev libc);
+  libc_lib = optionalString (libc != null) (getLib libc);
   cc_solib = getLib cc
     + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}";
 
   # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
-  coreutils_bin = if nativeTools then "" else getBin coreutils;
+  coreutils_bin = optionalString (!nativeTools) (getBin coreutils);
 
   # The "suffix salt" is a arbitrary string added in the end of env vars
   # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used
@@ -176,7 +176,7 @@ assert nativePrefix == bintools.nativePrefix;
 stdenv.mkDerivation {
   pname = targetPrefix
     + (if name != "" then name else "${ccName}-wrapper");
-  version = if cc == null then "" else ccVersion;
+  version = optionalString (cc != null) ccVersion;
 
   preferLocalBuild = true;
 
@@ -612,10 +612,10 @@ stdenv.mkDerivation {
     # for substitution in utils.bash
     expandResponseParams = "${expand-response-params}/bin/expand-response-params";
     shell = getBin shell + shell.shellPath or "";
-    gnugrep_bin = if nativeTools then "" else gnugrep;
+    gnugrep_bin = optionalString (!nativeTools) gnugrep;
     # stdenv.cc.cc should not be null and we have nothing better for now.
     # if the native impure bootstrap is gotten rid of this can become `inherit cc;` again.
-    cc = if nativeTools then "" else cc;
+    cc = optionalString (!nativeTools) cc;
     wrapperName = "CC_WRAPPER";
     inherit suffixSalt coreutils_bin bintools;
     inherit libc_bin libc_dev libc_lib;
diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix
index 5f48fb9f7bdbe..b74d7885d54ae 100644
--- a/pkgs/build-support/docker/default.nix
+++ b/pkgs/build-support/docker/default.nix
@@ -594,7 +594,7 @@ rec {
           nativeBuildInputs = [ jshon pigz jq moreutils ];
           # Image name must be lowercase
           imageName = lib.toLower name;
-          imageTag = if tag == null then "" else tag;
+          imageTag = lib.optionalString (tag != null) tag;
           inherit fromImage baseJson;
           layerClosure = writeReferencesToFile layer;
           passthru.buildArgs = args;
diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix
index faa338b672f0c..a2498700b545d 100644
--- a/pkgs/build-support/fetchgithub/default.nix
+++ b/pkgs/build-support/fetchgithub/default.nix
@@ -24,7 +24,7 @@ let
     position = "${position.file}:${toString position.line}";
   };
   passthruAttrs = removeAttrs args [ "owner" "repo" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ];
-  varBase = "NIX${if varPrefix == null then "" else "_${varPrefix}"}_GITHUB_PRIVATE_";
+  varBase = "NIX${lib.optionalString (varPrefix != null) "_${varPrefix}"}_GITHUB_PRIVATE_";
   useFetchGit = fetchSubmodules || (leaveDotGit == true) || deepClone || forceFetchGit || (sparseCheckout != []);
   # We prefer fetchzip in cases we don't need submodules as the hash
   # is more stable in that case.
diff --git a/pkgs/build-support/kernel/make-initrd-ng.nix b/pkgs/build-support/kernel/make-initrd-ng.nix
index f3cf3d59f92b0..2418838176ef3 100644
--- a/pkgs/build-support/kernel/make-initrd-ng.nix
+++ b/pkgs/build-support/kernel/make-initrd-ng.nix
@@ -72,7 +72,7 @@ in
   ${if makeUInitrd then "uInitrdCompression" else null} = uInitrdCompression;
 
   passAsFile = ["contents"];
-  contents = lib.concatMapStringsSep "\n" ({ object, symlink, ... }: "${object}\n${if symlink == null then "" else symlink}") contents + "\n";
+  contents = lib.concatMapStringsSep "\n" ({ object, symlink, ... }: "${object}\n${lib.optionalString (symlink != null) symlink}") contents + "\n";
 
   nativeBuildInputs = [makeInitrdNGTool cpio] ++ lib.optional makeUInitrd ubootTools ++ lib.optional strip binutils;
 
diff --git a/pkgs/build-support/nix-gitignore/default.nix b/pkgs/build-support/nix-gitignore/default.nix
index f8e673a2a7f50..c047bfc7d9a28 100644
--- a/pkgs/build-support/nix-gitignore/default.nix
+++ b/pkgs/build-support/nix-gitignore/default.nix
@@ -66,7 +66,7 @@ in rec {
       handleSlashPrefix = l:
         let
           split = (match "^(/?)(.*)" l);
-          findSlash = l: if (match ".+/.+" l) != null then "" else l;
+          findSlash = l: lib.optionalString ((match ".+/.+" l) == null) l;
           hasSlash = mapAroundCharclass findSlash l != l;
         in
           (if (elemAt split 0) == "/" || hasSlash
diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index 5168eb6ab7592..60310f178747e 100644
--- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -21,7 +21,7 @@
 , verbose
 , workspace_member }:
 let version_ = lib.splitString "-" crateVersion;
-    versionPre = if lib.tail version_ == [] then "" else lib.elemAt version_ 1;
+    versionPre = lib.optionalString (lib.tail version_ != []) (lib.elemAt version_ 1);
     version = lib.splitVersion (lib.head version_);
     rustcOpts = lib.foldl' (opts: opt: opts + " " + opt)
         (if release then "-C opt-level=3" else "-C debuginfo=2")
diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index 5cc107d2c4a8d..f6baa42348abf 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -468,7 +468,7 @@ rec {
 
         echo "installing RPMs..."
         PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \
-          rpm -iv --nosignature ${if runScripts then "" else "--noscripts"} $rpms
+          rpm -iv --nosignature ${lib.optionalString (!runScripts) "--noscripts"} $rpms
 
         echo "running post-install script..."
         eval "$postInstall"
diff --git a/pkgs/data/sgml+xml/stylesheets/xslt/docbook-xsl/default.nix b/pkgs/data/sgml+xml/stylesheets/xslt/docbook-xsl/default.nix
index 2f9d22e57d89e..66ebf105ffd0a 100644
--- a/pkgs/data/sgml+xml/stylesheets/xslt/docbook-xsl/default.nix
+++ b/pkgs/data/sgml+xml/stylesheets/xslt/docbook-xsl/default.nix
@@ -3,7 +3,7 @@
 let
 
   common = { pname, sha256, suffix ? "" }: let
-    legacySuffix = if suffix == "-nons" then "" else "-ns";
+    legacySuffix = lib.optionalString (suffix != "-nons") "-ns";
     self = stdenv.mkDerivation rec {
       inherit pname;
       version = "1.79.2";
diff --git a/pkgs/development/compilers/purescript/purescript/default.nix b/pkgs/development/compilers/purescript/purescript/default.nix
index d7c8394a57b17..fd3d1a810a5c3 100644
--- a/pkgs/development/compilers/purescript/purescript/default.nix
+++ b/pkgs/development/compilers/purescript/purescript/default.nix
@@ -7,10 +7,7 @@ let
   dynamic-linker = stdenv.cc.bintools.dynamicLinker;
 
   patchelf = libPath :
-    if stdenv.isDarwin
-      then ""
-      else
-        ''
+    lib.optionalString (!stdenv.isDarwin) ''
           chmod u+w $PURS
           patchelf --interpreter ${dynamic-linker} --set-rpath ${libPath} $PURS
           chmod u-w $PURS
diff --git a/pkgs/development/interpreters/acl2/libipasirglucose4/default.nix b/pkgs/development/interpreters/acl2/libipasirglucose4/default.nix
index dc8308267f40e..c31e0dbe67f73 100644
--- a/pkgs/development/interpreters/acl2/libipasirglucose4/default.nix
+++ b/pkgs/development/interpreters/acl2/libipasirglucose4/default.nix
@@ -24,7 +24,7 @@ stdenv.mkDerivation rec {
 
   postBuild = ''
     $CXX -shared -o ${libname} \
-        ${if stdenv.cc.isClang then "" else "-Wl,-soname,${libname}"} \
+        ${lib.optionalString (!stdenv.cc.isClang) "-Wl,-soname,${libname}"} \
         ipasirglucoseglue.o libipasirglucose4.a
   '';
 
diff --git a/pkgs/development/interpreters/python/mk-python-derivation.nix b/pkgs/development/interpreters/python/mk-python-derivation.nix
index 17b5667e8ee9c..79e45b8dc395b 100644
--- a/pkgs/development/interpreters/python/mk-python-derivation.nix
+++ b/pkgs/development/interpreters/python/mk-python-derivation.nix
@@ -118,7 +118,7 @@ let
 
     optionalLocation = let
         pos = builtins.unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs;
-      in if pos == null then "" else " at ${pos.file}:${toString pos.line}:${toString pos.column}";
+      in lib.optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
 
     leftPadName = name: against: let
         len = lib.max (lib.stringLength name) (lib.stringLength against);
diff --git a/pkgs/development/interpreters/python/wrapper.nix b/pkgs/development/interpreters/python/wrapper.nix
index b36662335abe2..f5f9b03e0fd3c 100644
--- a/pkgs/development/interpreters/python/wrapper.nix
+++ b/pkgs/development/interpreters/python/wrapper.nix
@@ -42,7 +42,7 @@ let
             if [ -f "$prg" ]; then
               rm -f "$out/bin/$prg"
               if [ -x "$prg" ]; then
-                makeWrapper "$path/bin/$prg" "$out/bin/$prg" --set NIX_PYTHONPREFIX "$out" --set NIX_PYTHONEXECUTABLE ${pythonExecutable} --set NIX_PYTHONPATH ${pythonPath} ${if permitUserSite then "" else ''--set PYTHONNOUSERSITE "true"''} ${lib.concatStringsSep " " makeWrapperArgs}
+                makeWrapper "$path/bin/$prg" "$out/bin/$prg" --set NIX_PYTHONPREFIX "$out" --set NIX_PYTHONEXECUTABLE ${pythonExecutable} --set NIX_PYTHONPATH ${pythonPath} ${lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} ${lib.concatStringsSep " " makeWrapperArgs}
               fi
             fi
           done
diff --git a/pkgs/development/libraries/ffmpeg/generic.nix b/pkgs/development/libraries/ffmpeg/generic.nix
index 7e11c60beb0d9..6bfb29f338fea 100644
--- a/pkgs/development/libraries/ffmpeg/generic.nix
+++ b/pkgs/development/libraries/ffmpeg/generic.nix
@@ -330,7 +330,7 @@ assert buildPostproc -> buildAvutil;
 assert buildSwscale -> buildAvutil;
 
 stdenv.mkDerivation (finalAttrs: {
-  pname = "ffmpeg" + (if ffmpegVariant == "small" then "" else "-${ffmpegVariant}");
+  pname = "ffmpeg" + (optionalString (ffmpegVariant != "small") "-${ffmpegVariant}");
   inherit version;
 
   src = fetchgit {
diff --git a/pkgs/development/libraries/liblcf/default.nix b/pkgs/development/libraries/liblcf/default.nix
index 45bb7f5b60edc..b91b6ea709adb 100644
--- a/pkgs/development/libraries/liblcf/default.nix
+++ b/pkgs/development/libraries/liblcf/default.nix
@@ -1,19 +1,39 @@
-{ lib, stdenv, fetchFromGitHub, autoreconfHook, pkg-config, expat, icu }:
+{ lib
+, stdenv
+, fetchFromGitHub
+, autoreconfHook
+, pkg-config
+, expat
+, icu
+}:
 
 stdenv.mkDerivation rec {
   pname = "liblcf";
-  version = "0.7.0";
+  version = "0.8";
 
   src = fetchFromGitHub {
     owner = "EasyRPG";
     repo = "liblcf";
     rev = version;
-    sha256 = "sha256-69cYZ8hJ92gK39gueaEoUM0K7BDWIQ/0NvcQ/6e3Sg8=";
+    hash = "sha256-jJGIsNw7wplTL5FBWGL8osb9255o9ZaWgl77R+RLDMM=";
   };
 
-  nativeBuildInputs = [ autoreconfHook pkg-config ];
-  propagatedBuildInputs = [ expat icu ];
+  dtrictDeps = true;
+
+  nativeBuildInputs = [
+    autoreconfHook
+    pkg-config
+  ];
+
+  propagatedBuildInputs = [
+    expat
+    icu
+  ];
+
   enableParallelBuilding = true;
+  enableParallelChecking = true;
+
+  doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
 
   meta = with lib; {
     description = "Library to handle RPG Maker 2000/2003 and EasyRPG projects";
diff --git a/pkgs/development/libraries/opencv/tests.nix b/pkgs/development/libraries/opencv/tests.nix
index 03a89db0882fa..d1966b1a4aa82 100644
--- a/pkgs/development/libraries/opencv/tests.nix
+++ b/pkgs/development/libraries/opencv/tests.nix
@@ -39,7 +39,7 @@ let
     "stitching"
     "video"
   ] ++ lib.optionals (!stdenv.isAarch64 && enableGStreamer) [ "gapi" ];
-  testRunner = if stdenv.isDarwin then "" else "${lib.getExe xvfb-run} -a ";
+  testRunner = lib.optionalString (!stdenv.isDarwin) "${lib.getExe xvfb-run} -a ";
   testsPreparation = ''
     touch $out
     # several tests want a write access, so we have to copy files
diff --git a/pkgs/development/libraries/qt-4.x/4.8/default.nix b/pkgs/development/libraries/qt-4.x/4.8/default.nix
index 68a300ac250dd..a8257a36d39d1 100644
--- a/pkgs/development/libraries/qt-4.x/4.8/default.nix
+++ b/pkgs/development/libraries/qt-4.x/4.8/default.nix
@@ -173,9 +173,9 @@ stdenv.mkDerivation rec {
     "-make" "libs" "-make" "tools" "-make" "translations"
     "-no-phonon" "-no-webkit" "-no-multimedia" "-audio-backend"
   ]) ++ [
-    "-${if demos then "" else "no"}make" "demos"
-    "-${if examples then "" else "no"}make" "examples"
-    "-${if docs then "" else "no"}make" "docs"
+    "-${lib.optionalString (!demos) "no"}make" "demos"
+    "-${lib.optionalString (!examples) "no"}make" "examples"
+    "-${lib.optionalString (!docs) "no"}make" "docs"
   ] ++ lib.optional developerBuild "-developer-build"
     ++ lib.optionals stdenv.hostPlatform.isDarwin [ platformFlag "unsupported/macx-clang-libc++" ]
     ++ lib.optionals stdenv.hostPlatform.isWindows [ platformFlag "win32-g++-4.6" ];
diff --git a/pkgs/development/mobile/titaniumenv/build-app.nix b/pkgs/development/mobile/titaniumenv/build-app.nix
index fa2eeae00b559..42b70c64abe9b 100644
--- a/pkgs/development/mobile/titaniumenv/build-app.nix
+++ b/pkgs/development/mobile/titaniumenv/build-app.nix
@@ -158,8 +158,7 @@ stdenv.mkDerivation ({
 
   installPhase = ''
     ${if target == "android" then ''
-      ${if release then ""
-      else ''
+      ${lib.optionalString (!release) ''
         cp "$(ls build/android/bin/*.apk | grep -v '\-unsigned.apk')" $out
       ''}
 
diff --git a/pkgs/development/python-modules/azure-common/default.nix b/pkgs/development/python-modules/azure-common/default.nix
index 504748f033ff4..47d0039e5e4bb 100644
--- a/pkgs/development/python-modules/azure-common/default.nix
+++ b/pkgs/development/python-modules/azure-common/default.nix
@@ -23,7 +23,7 @@ buildPythonPackage rec {
     azure-nspkg
   ] ++ lib.optionals (!isPy3k) [ setuptools ]; # need for namespace lookup
 
-  postInstall = if isPy3k then "" else ''
+  postInstall = lib.optionalString (!isPy3k) ''
     echo "__import__('pkg_resources').declare_namespace(__name__)" >> "$out/lib/${python.libPrefix}"/site-packages/azure/__init__.py
   '';
 
diff --git a/pkgs/development/python-modules/azure-mgmt-common/default.nix b/pkgs/development/python-modules/azure-mgmt-common/default.nix
index 28043046d8aa6..dfd7ac2a3f058 100644
--- a/pkgs/development/python-modules/azure-mgmt-common/default.nix
+++ b/pkgs/development/python-modules/azure-mgmt-common/default.nix
@@ -26,7 +26,7 @@ buildPythonPackage rec {
     msrestazure
   ];
 
-  postInstall = if isPy3k then "" else ''
+  postInstall = pkgs.lib.optionalString (!isPy3k) ''
     echo "__import__('pkg_resources').declare_namespace(__name__)" >> "$out/lib/${python.libPrefix}"/site-packages/azure/mgmt/__init__.py
     echo "__import__('pkg_resources').declare_namespace(__name__)" >> "$out/lib/${python.libPrefix}"/site-packages/azure/__init__.py
   '';
diff --git a/pkgs/development/python-modules/hcloud/default.nix b/pkgs/development/python-modules/hcloud/default.nix
index 35c7e2d651774..9a1ecc4294300 100644
--- a/pkgs/development/python-modules/hcloud/default.nix
+++ b/pkgs/development/python-modules/hcloud/default.nix
@@ -11,14 +11,14 @@
 
 buildPythonPackage rec {
   pname = "hcloud";
-  version = "1.25.0";
+  version = "1.26.0";
   format = "setuptools";
 
   disabled = pythonOlder "3.7";
 
   src = fetchPypi {
     inherit pname version;
-    hash = "sha256-xKoyRwMeyU+qQ0wXsVCTXdQatxQCc5re2Iv6KGjusuA=";
+    hash = "sha256-siyPuSLqzH30bdY1y+VaBBCjOU1YLtBgPpTvZCJtcXc=";
   };
 
   propagatedBuildInputs = [
diff --git a/pkgs/development/python-modules/pyfuse3/default.nix b/pkgs/development/python-modules/pyfuse3/default.nix
index 8e11960026415..45dbd1a43ae2c 100644
--- a/pkgs/development/python-modules/pyfuse3/default.nix
+++ b/pkgs/development/python-modules/pyfuse3/default.nix
@@ -14,7 +14,7 @@
 
 buildPythonPackage rec {
   pname = "pyfuse3";
-  version = "3.2.2";
+  version = "3.2.3";
 
   disabled = pythonOlder "3.5";
 
@@ -24,7 +24,7 @@ buildPythonPackage rec {
     owner = "libfuse";
     repo = "pyfuse3";
     rev = "refs/tags/${version}";
-    hash = "sha256-Y9Haz3MMhTXkvYFOGNWJnoGNnvoK6wiQ+s3AwJhBD8Q=";
+    hash = "sha256-2YrVapCojcFRaljqNeWPMWz3hEgSutKPy2u8FXp0fME=";
   };
 
   postPatch = ''
diff --git a/pkgs/development/python-modules/pymilvus/default.nix b/pkgs/development/python-modules/pymilvus/default.nix
index 983cc7566df66..ba22546099a32 100644
--- a/pkgs/development/python-modules/pymilvus/default.nix
+++ b/pkgs/development/python-modules/pymilvus/default.nix
@@ -17,7 +17,7 @@
 
 buildPythonPackage rec {
   pname = "pymilvus";
-  version = "2.2.8";
+  version = "2.2.13";
   format = "pyproject";
 
   disabled = pythonOlder "3.7";
@@ -26,7 +26,7 @@ buildPythonPackage rec {
     owner = "milvus-io";
     repo = pname;
     rev = "refs/tags/v${version}";
-    hash = "sha256-Oqwa/2UT9jyGaEEzjr/phZZStLOZ6JRj+4ck0tmP0W0=";
+    hash = "sha256-NTzdbmI2vNvNBFhN+xyZewH4b6l1BbKkDDE7rLNJ4IE=";
   };
 
   SETUPTOOLS_SCM_PRETEND_VERSION = version;
diff --git a/pkgs/development/python-modules/rauth/default.nix b/pkgs/development/python-modules/rauth/default.nix
new file mode 100644
index 0000000000000..059dfa9a2a60d
--- /dev/null
+++ b/pkgs/development/python-modules/rauth/default.nix
@@ -0,0 +1,54 @@
+{ lib
+, buildPythonPackage
+, fetchFromGitHub
+, fetchpatch
+, requests
+, pytestCheckHook
+, mock
+, nose
+, pycrypto
+}:
+
+buildPythonPackage rec {
+  pname = "rauth";
+  version = "0.7.2";
+  format = "setuptools";
+
+  src = fetchFromGitHub {
+    owner = "litl";
+    repo = "rauth";
+    rev = version;
+    hash = "sha256-wRKZbxZCEfihOaJM8sk8438LE++KJWxdOGImpL1gHa4=";
+  };
+
+  patches = [
+    (fetchpatch {
+      # https://github.com/litl/rauth/pull/211
+      name = "fix-pycrypdodome-replacement-for-pycrypto.patch";
+      url = "https://github.com/litl/rauth/commit/7fb3b7bf1a1869a52cf59ee3eb607d318e97265c.patch";
+      hash = "sha256-jiAIw+VQ2d/bkm2brqfY1RUrNGf+lsMPnoI91gGUS6o=";
+    })
+  ];
+
+  propagatedBuildInputs = [
+    requests
+  ];
+
+  pythonImportsCheck = [ "rauth" ];
+
+  nativeCheckInputs = [
+    pytestCheckHook
+    mock
+    nose
+    pycrypto
+  ];
+
+  meta = with lib; {
+    description = "A Python library for OAuth 1.0/a, 2.0, and Ofly";
+    homepage = "https://github.com/litl/rauth";
+    changelog = "https://github.com/litl/rauth/blob/${src.rev}/CHANGELOG";
+    license = licenses.mit;
+    maintainers = with maintainers; [ blaggacao ];
+  };
+}
+
diff --git a/pkgs/development/python-modules/tensorflow/bin.nix b/pkgs/development/python-modules/tensorflow/bin.nix
index a988a39c388b2..5bb668965048e 100644
--- a/pkgs/development/python-modules/tensorflow/bin.nix
+++ b/pkgs/development/python-modules/tensorflow/bin.nix
@@ -53,7 +53,7 @@ in buildPythonPackage {
   disabled = pythonAtLeast "3.11";
 
   src = let
-    pyVerNoDot = lib.strings.stringAsChars (x: if x == "." then "" else x) python.pythonVersion;
+    pyVerNoDot = lib.strings.stringAsChars (x: lib.optionalString (x != ".") x) python.pythonVersion;
     platform = if stdenv.isDarwin then "mac" else "linux";
     unit = if cudaSupport then "gpu" else "cpu";
     key = "${platform}_py_${pyVerNoDot}_${unit}";
diff --git a/pkgs/development/python-modules/types-deprecated/default.nix b/pkgs/development/python-modules/types-deprecated/default.nix
index cc1102c035530..ee4ede8620f57 100644
--- a/pkgs/development/python-modules/types-deprecated/default.nix
+++ b/pkgs/development/python-modules/types-deprecated/default.nix
@@ -5,13 +5,13 @@
 
 buildPythonPackage rec {
   pname = "types-deprecated";
-  version = "1.2.9.2";
+  version = "1.2.9.3";
   format = "setuptools";
 
   src = fetchPypi {
     pname = "types-Deprecated";
     inherit version;
-    hash = "sha256-kWFv1nRfi/LUV/u779FM3kODjp8AoEtaDq5Pwfe7xpc=";
+    hash = "sha256-74cyet8+PEpMfY4G5Y9kdnENNGbs+1PEnvsICASnDvM=";
   };
 
   # Modules has no tests
diff --git a/pkgs/development/ruby-modules/bundled-common/default.nix b/pkgs/development/ruby-modules/bundled-common/default.nix
index b18248c7d61b8..86c885b52dcb4 100644
--- a/pkgs/development/ruby-modules/bundled-common/default.nix
+++ b/pkgs/development/ruby-modules/bundled-common/default.nix
@@ -70,11 +70,12 @@ let
       assert gemFiles.gemdir != null; "cp -a ${gemFiles.gemdir}/* $out/") #*/
   );
 
-  maybeCopyAll = pkgname: if pkgname == null then "" else
-  let
-    mainGem = gems.${pkgname} or (throw "bundlerEnv: gem ${pkgname} not found");
-  in
-    copyIfBundledByPath mainGem;
+  maybeCopyAll = pkgname: lib.optionalString (pkgname != null) (
+    let
+      mainGem = gems.${pkgname} or (throw "bundlerEnv: gem ${pkgname} not found");
+    in
+      copyIfBundledByPath mainGem
+  );
 
   # We have to normalize the Gemfile.lock, otherwise bundler tries to be
   # helpful by doing so at run time, causing executables to immediately bail
diff --git a/pkgs/development/ruby-modules/gem/default.nix b/pkgs/development/ruby-modules/gem/default.nix
index b33758486eed1..7ae9168975ab6 100644
--- a/pkgs/development/ruby-modules/gem/default.nix
+++ b/pkgs/development/ruby-modules/gem/default.nix
@@ -233,7 +233,7 @@ stdenv.mkDerivation ((builtins.removeAttrs attrs ["source"]) // {
     pushd $out/${ruby.gemPath}
     find doc/ -iname created.rid -delete -print
     find gems/*/ext/ extensions/ \( -iname Makefile -o -iname mkmf.log -o -iname gem_make.out \) -delete -print
-    ${if keepGemCache then "" else "rm -fvr cache"}
+    ${lib.optionalString (!keepGemCache) "rm -fvr cache"}
     popd
 
     # write out metadata and binstubs
diff --git a/pkgs/development/tools/flyway/default.nix b/pkgs/development/tools/flyway/default.nix
index 8de62a6369084..c34b89d362088 100644
--- a/pkgs/development/tools/flyway/default.nix
+++ b/pkgs/development/tools/flyway/default.nix
@@ -1,10 +1,10 @@
 { lib, stdenv, fetchurl, jre_headless, makeWrapper }:
 stdenv.mkDerivation rec{
   pname = "flyway";
-  version = "9.18.0";
+  version = "9.21.0";
   src = fetchurl {
     url = "mirror://maven/org/flywaydb/flyway-commandline/${version}/flyway-commandline-${version}.tar.gz";
-    sha256 = "sha256-fsw4gzp3R9ZgN3ZVr0xLUCqckEHA4OSpIdwiKYp06AM=";
+    sha256 = "sha256-jy+hgEmLs2jfW5zD9gIKUltcb4zD8hxLiP7ZyKLMpoU=";
   };
   nativeBuildInputs = [ makeWrapper ];
   dontBuild = true;
diff --git a/pkgs/development/tools/misc/distcc/default.nix b/pkgs/development/tools/misc/distcc/default.nix
index b7270f79c4315..312f693285801 100644
--- a/pkgs/development/tools/misc/distcc/default.nix
+++ b/pkgs/development/tools/misc/distcc/default.nix
@@ -26,7 +26,7 @@ let
       configureFlagsArray=( CFLAGS="-O2 -fno-strict-aliasing"
                             CXXFLAGS="-O2 -fno-strict-aliasing"
           --mandir=$out/share/man
-                            ${if sysconfDir == "" then "" else "--sysconfdir=${sysconfDir}"}
+                            ${lib.optionalString (sysconfDir != "") "--sysconfdir=${sysconfDir}"}
                             ${lib.optionalString static "LDFLAGS=-static"}
                             ${lib.withFeature (static == true || popt == null) "included-popt"}
                             ${lib.withFeature (avahi != null) "avahi"}
diff --git a/pkgs/development/web/nodejs/v20.nix b/pkgs/development/web/nodejs/v20.nix
index 07fb168eeb9a3..b1b5aea5768af 100644
--- a/pkgs/development/web/nodejs/v20.nix
+++ b/pkgs/development/web/nodejs/v20.nix
@@ -9,8 +9,8 @@ let
 in
 buildNodejs {
   inherit enableNpm;
-  version = "20.4.0";
-  sha256 = "sha256-Cb0Lc8UmtjwCnV3f2IXRCWLnrYfJdblFg8H4zpDuU0g=";
+  version = "20.5.0";
+  sha256 = "sha256-yzJ1aVje8cBOBpp5txtSymHtFZDBfyz6HuOvZB9y4Fg=";
   patches = [
     ./revert-arm64-pointer-auth.patch
     ./disable-darwin-v8-system-instrumentation-node19.patch
diff --git a/pkgs/games/easyrpg-player/default.nix b/pkgs/games/easyrpg-player/default.nix
index c95ca576ecac2..ea68c3a110e21 100644
--- a/pkgs/games/easyrpg-player/default.nix
+++ b/pkgs/games/easyrpg-player/default.nix
@@ -1,23 +1,71 @@
-{ lib, stdenv, fetchFromGitHub, cmake, doxygen ? null, pkg-config
-, freetype ? null, fmt, glib, harfbuzz ? null
-, liblcf, libpng, libsndfile ? null, libvorbis ? null, libxmp ? null
-, libXcursor, libXext, libXi, libXinerama, libXrandr, libXScrnSaver, libXxf86vm
-, mpg123 ? null, opusfile ? null, pcre, pixman, SDL2, speexdsp ? null, wildmidi ? null, zlib
+{ lib
+, stdenv
+, fetchFromGitHub
+, fetchpatch
+, cmake
+, doxygen
+, pkg-config
+, freetype
+, fmt
+, glib
+, harfbuzz
+, liblcf
+, libpng
+, libsndfile
+, libvorbis
+, libxmp
+, libXcursor
+, libXext
+, libXi
+, libXinerama
+, libXrandr
+, libXScrnSaver
+, libXxf86vm
+, mpg123
+, opusfile
+, pcre
+, pixman
+, SDL2
+, speexdsp
+, wildmidi
+, zlib
 , libdecor
+, alsa-lib
+, asciidoctor
+, Foundation
+, AudioUnit
+, AudioToolbox
 }:
 
 stdenv.mkDerivation rec {
   pname = "easyrpg-player";
-  version = "0.7.0";
+  version = "0.8";
 
   src = fetchFromGitHub {
     owner = "EasyRPG";
     repo = "Player";
     rev = version;
-    sha256 = "049bj3jg3ldi3n11nx8xvh6pll68g7dcxz51q6z1gyyfxxws1qpj";
+    hash = "sha256-t0sa9ONVVfsiTy+us06vU2bMa4QmmQeYxU395g0WS6w=";
   };
 
-  nativeBuildInputs = [ cmake doxygen pkg-config ];
+  patches = [
+    # Fixed compatibility with fmt > 9
+    # Remove when version > 0.8
+    (fetchpatch {
+      name = "0001-Fix-building-with-fmtlib-10.patch";
+      url = "https://github.com/EasyRPG/Player/commit/ab6286f6d01bada649ea52d1f0881dde7db7e0cf.patch";
+      hash = "sha256-GdSdVFEG1OJCdf2ZIzTP+hSrz+ddhTMBvOPjvYQHy54=";
+    })
+  ];
+
+  strictDeps = true;
+
+  nativeBuildInputs = [
+    asciidoctor
+    cmake
+    doxygen
+    pkg-config
+  ];
 
   buildInputs = [
     fmt
@@ -29,29 +77,59 @@ stdenv.mkDerivation rec {
     libsndfile
     libvorbis
     libxmp
-    libXcursor
-    libXext
-    libXi
-    libXinerama
-    libXrandr
-    libXScrnSaver
-    libXxf86vm
     mpg123
     opusfile
     pcre
     pixman
     SDL2
     speexdsp
-    wildmidi
     zlib
+  ] ++ lib.optionals stdenv.hostPlatform.isLinux [
+    alsa-lib
+    libXcursor
+    libXext
+    libXi
+    libXinerama
+    libXrandr
+    libXScrnSaver
+    libXxf86vm
     libdecor
+    wildmidi # until packaged on Darwin
+  ] ++ lib.optionals stdenv.hostPlatform.isDarwin [
+    Foundation
+    AudioUnit
+    AudioToolbox
   ];
 
+  cmakeFlags = [
+    "-DPLAYER_ENABLE_TESTS=${lib.boolToString doCheck}"
+  ];
+
+  makeFlags = [
+    "all"
+    "man"
+  ];
+
+  buildFlags = lib.optionals doCheck [
+    "test_runner_player"
+  ];
+
+  postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
+    mkdir $out/bin
+    mv Package $out/Applications
+    ln -s $out/{Applications/EasyRPG\ Player.app/Contents/MacOS,bin}/EasyRPG\ Player
+  '';
+
+  doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
+
+  enableParallelChecking = true;
+
   meta = with lib; {
     description = "RPG Maker 2000/2003 and EasyRPG games interpreter";
     homepage = "https://easyrpg.org/";
     license = licenses.gpl3;
     maintainers = with maintainers; [ yana ];
-    platforms = platforms.linux;
+    platforms = platforms.all;
+    mainProgram = lib.optionalString stdenv.hostPlatform.isDarwin "EasyRPG Player";
   };
 }
diff --git a/pkgs/os-specific/linux/kernel/manual-config.nix b/pkgs/os-specific/linux/kernel/manual-config.nix
index 60175f805a688..07325f0e10b07 100644
--- a/pkgs/os-specific/linux/kernel/manual-config.nix
+++ b/pkgs/os-specific/linux/kernel/manual-config.nix
@@ -409,10 +409,11 @@ stdenv.mkDerivation ({
   meta = {
     description =
       "The Linux kernel" +
-      (if kernelPatches == [] then "" else
+      (lib.optionalString (kernelPatches != []) (
         " (with patches: "
         + lib.concatStringsSep ", " (map (x: x.name) kernelPatches)
-        + ")");
+        + ")"
+      ));
     license = lib.licenses.gpl2Only;
     homepage = "https://www.kernel.org/";
     maintainers = lib.teams.linux-kernel.members ++ [
diff --git a/pkgs/servers/mail/mox/default.nix b/pkgs/servers/mail/mox/default.nix
new file mode 100644
index 0000000000000..2dd7712c2c887
--- /dev/null
+++ b/pkgs/servers/mail/mox/default.nix
@@ -0,0 +1,34 @@
+{ lib
+, buildGoModule
+, fetchFromGitHub
+}:
+
+buildGoModule rec {
+  pname = "mox";
+  version = "0.0.5";
+
+  src = fetchFromGitHub {
+    owner = "mjl-";
+    repo = "mox";
+    rev = "v${version}";
+    hash = "sha256-f5/K6cPqJJkbdiVCNGOTd9Fjx2/gvSZCxeR6nnEaeJw=";
+  };
+
+  # set the version during buildtime
+  patches = [ ./version.patch ];
+
+  vendorHash = null;
+
+  ldflags = [
+    "-s"
+    "-w"
+    "-X github.com/mjl-/mox/moxvar.Version=${version}"
+  ];
+
+  meta = {
+    description = "Modern full-featured open source secure mail server for low-maintenance self-hosted email";
+    homepage = "https://github.com/mjl-/mox";
+    license = lib.licenses.mit;
+    maintainers = with lib.maintainers; [ dit7ya ];
+  };
+}
diff --git a/pkgs/servers/mail/mox/version.patch b/pkgs/servers/mail/mox/version.patch
new file mode 100644
index 0000000000000..c842275ac9e49
--- /dev/null
+++ b/pkgs/servers/mail/mox/version.patch
@@ -0,0 +1,45 @@
+diff --git a/moxvar/version.go b/moxvar/version.go
+index 8c6bac8..69b5f7c 100644
+--- a/moxvar/version.go
++++ b/moxvar/version.go
+@@ -1,38 +1,5 @@
+ // Package moxvar provides the version number of a mox build.
+ package moxvar
+ 
+-import (
+-	"runtime/debug"
+-)
+-
+-// Version is set at runtime based on the Go module used to build.
+-var Version = "(devel)"
+-
+-func init() {
+-	buildInfo, ok := debug.ReadBuildInfo()
+-	if !ok {
+-		return
+-	}
+-	Version = buildInfo.Main.Version
+-	if Version == "(devel)" {
+-		var vcsRev, vcsMod string
+-		for _, setting := range buildInfo.Settings {
+-			if setting.Key == "vcs.revision" {
+-				vcsRev = setting.Value
+-			} else if setting.Key == "vcs.modified" {
+-				vcsMod = setting.Value
+-			}
+-		}
+-		if vcsRev == "" {
+-			return
+-		}
+-		Version = vcsRev
+-		switch vcsMod {
+-		case "false":
+-		case "true":
+-			Version += "+modifications"
+-		default:
+-			Version += "+unknown"
+-		}
+-	}
+-}
++// Version is set via a build flag
++var Version string;
diff --git a/pkgs/servers/miniflux/default.nix b/pkgs/servers/miniflux/default.nix
index a206f7b77e578..c89b4f15add1f 100644
--- a/pkgs/servers/miniflux/default.nix
+++ b/pkgs/servers/miniflux/default.nix
@@ -2,7 +2,7 @@
 
 let
   pname = "miniflux";
-  version = "2.0.45";
+  version = "2.0.46";
 
 in buildGoModule {
   inherit pname version;
@@ -11,10 +11,10 @@ in buildGoModule {
     owner = pname;
     repo = "v2";
     rev = version;
-    sha256 = "sha256-/d5+Qc2kXZZkKe80+879YdxYt+zy/Y1sf2dwSjGw0EM=";
+    sha256 = "sha256-a27eKOhW2vHmPktLgqHKqiwtC9T6GRwnOeNReeMsaeM=";
   };
 
-  vendorHash = "sha256-nwKo4Sjg8HjuxeDUgwQYZ2LOHxkRSlyaBlQwSjOuJ7U=";
+  vendorHash = "sha256-Oe7el4tE/gwI6qL/fjJgnv1jbNSKrCnq1nBq+dD7Gik=";
 
   nativeBuildInputs = [ installShellFiles ];
 
diff --git a/pkgs/servers/sql/pgbouncer/default.nix b/pkgs/servers/sql/pgbouncer/default.nix
index 7d3d3e949ed3f..e47818b8d2f08 100644
--- a/pkgs/servers/sql/pgbouncer/default.nix
+++ b/pkgs/servers/sql/pgbouncer/default.nix
@@ -1,4 +1,4 @@
-{ lib, stdenv, fetchurl, openssl, libevent, c-ares, pkg-config }:
+{ lib, stdenv, fetchurl, openssl, libevent, c-ares, pkg-config, nixosTests }:
 
 stdenv.mkDerivation rec {
   pname = "pgbouncer";
@@ -13,6 +13,10 @@ stdenv.mkDerivation rec {
   buildInputs = [ libevent openssl c-ares ];
   enableParallelBuilding = true;
 
+  passthru.tests = {
+    pgbouncer = nixosTests.pgbouncer;
+  };
+
   meta = with lib; {
     homepage = "https://www.pgbouncer.org/";
     description = "Lightweight connection pooler for PostgreSQL";
diff --git a/pkgs/shells/zsh/grml-zsh-config/default.nix b/pkgs/shells/zsh/grml-zsh-config/default.nix
index 47dc4748c1f52..1e2e9f29b25a0 100644
--- a/pkgs/shells/zsh/grml-zsh-config/default.nix
+++ b/pkgs/shells/zsh/grml-zsh-config/default.nix
@@ -5,13 +5,13 @@ with lib;
 
 stdenv.mkDerivation rec {
   pname = "grml-zsh-config";
-  version = "0.19.5";
+  version = "0.19.6";
 
   src = fetchFromGitHub {
     owner = "grml";
     repo = "grml-etc-core";
     rev = "v${version}";
-    sha256 = "sha256-/phoIi8amqdO+OK26+CE2OXwHTE71PaV9NIXEnGl6Co=";
+    sha256 = "sha256-31BD5jUA54oLSsL4NzGaGAiOXMcZwy7uX65pD+jtE4M=";
   };
 
   strictDeps = true;
diff --git a/pkgs/tools/admin/eksctl/default.nix b/pkgs/tools/admin/eksctl/default.nix
index f01edc1d61097..3a8f2801e96ef 100644
--- a/pkgs/tools/admin/eksctl/default.nix
+++ b/pkgs/tools/admin/eksctl/default.nix
@@ -2,16 +2,16 @@
 
 buildGoModule rec {
   pname = "eksctl";
-  version = "0.148.0";
+  version = "0.150.0";
 
   src = fetchFromGitHub {
     owner = "weaveworks";
     repo = pname;
     rev = version;
-    hash = "sha256-0/gjBUbngj6lVw3ascI0P+n95IkjsDhEq5x72P5DnSg=";
+    hash = "sha256-JmmbIeLr9jxr+LgVOw/IyIxkun0aTvdvq1e/EPUvvng=";
   };
 
-  vendorHash = "sha256-30OmvzC0Sd0ce2IAleE7prQBlMvMGvUGF5IfrG2m0IQ=";
+  vendorHash = "sha256-zSRsPO7ms7k2B+KEOUIqc6hZuKJ2lpZatnBQWjqFdJA=";
 
   doCheck = false;
 
diff --git a/pkgs/tools/networking/ebpf-verifier/default.nix b/pkgs/tools/networking/ebpf-verifier/default.nix
new file mode 100644
index 0000000000000..63af32ce1a207
--- /dev/null
+++ b/pkgs/tools/networking/ebpf-verifier/default.nix
@@ -0,0 +1,60 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, boost
+, cmake
+, catch2
+, pkg-config
+, substituteAll
+, yaml-cpp
+}:
+
+stdenv.mkDerivation (finalAttrs: {
+  pname = "ebpf-verifier";
+  version = "unstable-2023-07-15";
+
+  src = fetchFromGitHub {
+    owner = "vbpf";
+    repo = "ebpf-verifier";
+    rev = "de14d3aa3cd2845b621faf32b599766a66e158cf";
+    fetchSubmodules = true;
+    hash = "sha256-gnxB8ZLbTyIYpd61T57LPKFm1MHufeVEq/qN9pu2Vpk=";
+  };
+
+  patches = [
+    (substituteAll {
+      # We will download them instead of cmake's fetchContent
+      src = ./remove-fetchcontent-usage.patch;
+      catch2Src = catch2.src;
+    })
+  ];
+
+  nativeBuildInputs = [
+    pkg-config
+    cmake
+  ];
+
+  buildInputs = [
+    boost
+    yaml-cpp
+  ];
+
+  cmakeFlags = [ "-DCMAKE_BUILD_TYPE=Release" ];
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/bin
+    cp ../check $out/bin/ebpf-verifier
+
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "eBPF verifier based on abstract interpretation";
+    homepage = "https://github.com/vbpf/ebpf-verifier";
+    license = licenses.mit;
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ gaelreyrol ];
+  };
+})
diff --git a/pkgs/tools/networking/ebpf-verifier/remove-fetchcontent-usage.patch b/pkgs/tools/networking/ebpf-verifier/remove-fetchcontent-usage.patch
new file mode 100644
index 0000000000000..8a4af1bee19a0
--- /dev/null
+++ b/pkgs/tools/networking/ebpf-verifier/remove-fetchcontent-usage.patch
@@ -0,0 +1,14 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index d7cf256..cb94e5a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -6,8 +6,7 @@ project(ebpf_verifier)
+ include(FetchContent)
+ FetchContent_Declare(
+   Catch2
+-  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+-  GIT_TAG        ac93f1943762f6fc92f0dc5bac0d720a33a27530
++  SOURCE_DIR @catch2Src@
+ )
+ FetchContent_MakeAvailable(Catch2)
+ 
diff --git a/pkgs/tools/security/cnspec/default.nix b/pkgs/tools/security/cnspec/default.nix
index 6bd060154fa04..5c835d34eb0a8 100644
--- a/pkgs/tools/security/cnspec/default.nix
+++ b/pkgs/tools/security/cnspec/default.nix
@@ -5,17 +5,17 @@
 
 buildGoModule rec {
   pname = "cnspec";
-  version = "8.18.0";
+  version = "8.19.0";
 
   src = fetchFromGitHub {
     owner = "mondoohq";
     repo = "cnspec";
     rev = "refs/tags/v${version}";
-    hash = "sha256-JlFPJ4tbpxt/UBXpQCod3zythOHP9wQ8yqAMqKAyqoU=";
+    hash = "sha256-0vRhEkkyZMcqA5CGq1oDnODCTSzstpkVOGv2WrPnuWY=";
   };
 
   proxyVendor = true;
-  vendorHash = "sha256-RDQQVl3AxdZaF4ISQiQ8ZliZi6TWwIzYLZLxs0yPkJc=";
+  vendorHash = "sha256-UH46ejn6SfXjkyKaM3mX4IYgyNbt2mp9ycl2M+3xvU0=";
 
   subPackages = [
     "apps/cnspec"
diff --git a/pkgs/tools/security/jadx/default.nix b/pkgs/tools/security/jadx/default.nix
index 2911c369b0b7d..10f67d5f0b356 100644
--- a/pkgs/tools/security/jadx/default.nix
+++ b/pkgs/tools/security/jadx/default.nix
@@ -1,4 +1,15 @@
-{ lib, stdenv, fetchFromGitHub, gradle, jdk, makeWrapper, perl }:
+{ lib
+, stdenv
+, fetchFromGitHub
+, gradle
+, jdk
+, makeWrapper
+, perl
+, imagemagick
+, makeDesktopItem
+, copyDesktopItems
+, desktopToDarwinBundle
+}:
 
 let
   pname = "jadx";
@@ -46,10 +57,11 @@ let
     outputHashMode = "recursive";
     outputHash = "sha256-QebPRmfLtXy4ZlyKeGC5XNzhMTsYI0X36My+nTFvQpM=";
   };
-in stdenv.mkDerivation {
+in stdenv.mkDerivation (finalAttrs: {
   inherit pname version src;
 
-  nativeBuildInputs = [ gradle jdk makeWrapper ];
+  nativeBuildInputs = [ gradle jdk imagemagick makeWrapper copyDesktopItems ]
+    ++ lib.optionals stdenv.hostPlatform.isDarwin [ desktopToDarwinBundle ];
 
   # Otherwise, Gradle fails with `java.net.SocketException: Operation not permitted`
   __darwinAllowLocalNetworking = true;
@@ -96,14 +108,39 @@ in stdenv.mkDerivation {
   '';
 
   installPhase = ''
+    runHook preInstall
+
     mkdir $out $out/bin
     cp -R build/jadx/lib $out
     for prog in jadx jadx-gui; do
       cp build/jadx/bin/$prog $out/bin
       wrapProgram $out/bin/$prog --set JAVA_HOME ${jdk.home}
     done
+
+    for size in 16 32 48; do
+      install -Dm444 \
+        jadx-gui/src/main/resources/logos/jadx-logo-"$size"px.png \
+        $out/share/icons/hicolor/"$size"x"$size"/apps/jadx.png
+    done
+    for size in 64 128 256; do
+      mkdir -p $out/share/icons/hicolor/"$size"x"$size"/apps
+      convert -resize "$size"x"$size" jadx-gui/src/main/resources/logos/jadx-logo.png $out/share/icons/hicolor/"$size"x"$size"/apps/jadx.png
+    done
+
+    runHook postInstall
   '';
 
+  desktopItems = [
+    (makeDesktopItem {
+      name = "jadx";
+      desktopName = "JADX";
+      exec = "jadx-gui";
+      icon = "jadx";
+      comment = finalAttrs.meta.description;
+      categories = [ "Development" "Utility" ];
+    })
+  ];
+
   meta = with lib; {
     description = "Dex to Java decompiler";
     longDescription = ''
@@ -118,4 +155,4 @@ in stdenv.mkDerivation {
     platforms = platforms.unix;
     maintainers = with maintainers; [ delroth ];
   };
-}
+})
diff --git a/pkgs/tools/text/fanficfare/default.nix b/pkgs/tools/text/fanficfare/default.nix
index 0780f4a33b63a..7d27a45b56fd1 100644
--- a/pkgs/tools/text/fanficfare/default.nix
+++ b/pkgs/tools/text/fanficfare/default.nix
@@ -2,11 +2,11 @@
 
 python3Packages.buildPythonApplication rec {
   pname = "FanFicFare";
-  version = "4.24.0";
+  version = "4.25.0";
 
   src = fetchPypi {
     inherit pname version;
-    hash = "sha256-DQaiP0EIvP0gT0b0nqJT18xqd5J5tuwIp6y7bpNH6tA=";
+    hash = "sha256-ky6N/AcfoXJahW7tw++WtnpTnpRv4ZUraMTWjVXDjEE=";
   };
 
   propagatedBuildInputs = with python3Packages; [
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 1213ba7dec7a8..7bb8e22f00373 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -591,6 +591,17 @@ with pkgs;
 
   eclipse-mat = callPackage ../development/tools/eclipse-mat { };
 
+  ebpf-verifier = callPackage ../tools/networking/ebpf-verifier {
+    # Replace this to `catch2 = catch2_3` when catch2 3.4.0 is merged
+    # https://github.com/NixOS/nixpkgs/pull/243485
+    catch2.src = fetchFromGitHub {
+      owner = "catchorg";
+      repo = "Catch2";
+      rev = "v3.4.0";
+      hash = "sha256-DqGGfNjKPW9HFJrX9arFHyNYjB61uoL6NabZatTWrr0=";
+    };
+  };
+
   edgedb = callPackage ../tools/networking/edgedb {
     inherit (darwin.apple_sdk.frameworks) CoreServices Security;
   };
@@ -6242,6 +6253,8 @@ with pkgs;
 
   mountain-duck = callPackage ../tools/filesystems/mountain-duck { };
 
+  mox = callPackage ../servers/mail/mox { };
+
   mozlz4a = callPackage ../tools/compression/mozlz4a { };
 
   msr-tools = callPackage ../os-specific/linux/msr-tools { };
@@ -37116,7 +37129,9 @@ with pkgs;
     d1x-rebirth-full
     d2x-rebirth-full;
 
-  easyrpg-player = callPackage ../games/easyrpg-player { };
+  easyrpg-player = callPackage ../games/easyrpg-player {
+    inherit (darwin.apple_sdk.frameworks) Foundation AudioUnit AudioToolbox;
+  };
 
   eboard = callPackage ../games/eboard { };
 
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index f034c9a4c214f..3fcb689e14749 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -10742,6 +10742,8 @@ self: super: with self; {
 
   ratelimiter = callPackage ../development/python-modules/ratelimiter { };
 
+  rauth = callPackage ../development/python-modules/rauth { };
+
   raven = callPackage ../development/python-modules/raven { };
 
   rawkit = callPackage ../development/python-modules/rawkit { };