diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index e3c61c882cb4..e6e7befe7066 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -310,6 +310,8 @@ - `hardware.pulseaudio` has been renamed to `services.pulseaudio`. The deprecated option names will continue to work, but causes a warning. +- `services.nextcloud` now uses systemd's credential mechanism to read in secret files. The `nextcloud-occ` wrapper script implements this using `systemd-run`, as such it now also requires root privileges or `$CREDENTIALS_DIRECTORY` set where running it as user `nextcloud` was enough previously. + - `minetest` has been renamed to `luanti` to match the upstream name change but aliases have been added. The new name hasn't resulted in many changes as of yet but older references to minetest should be sunset. See the [new name announcement](https://blog.minetest.net/2024/10/13/Introducing-Our-New-Name/) for more details. - `poac` has been renamed to `cabinpkg` to match the upstream name change but an alias has been added. See the [new name announcement](https://github.com/orgs/cabinpkg/discussions/1052) for more details. diff --git a/nixos/modules/services/web-apps/nextcloud-notify_push.nix b/nixos/modules/services/web-apps/nextcloud-notify_push.nix index b136d43daef1..1246a6e6394c 100644 --- a/nixos/modules/services/web-apps/nextcloud-notify_push.nix +++ b/nixos/modules/services/web-apps/nextcloud-notify_push.nix @@ -78,60 +78,75 @@ in ); config = lib.mkIf cfg.enable { - systemd.services.nextcloud-notify_push = { - description = "Push daemon for Nextcloud clients"; - documentation = [ "https://github.com/nextcloud/notify_push" ]; - after = [ - "phpfpm-nextcloud.service" - "redis-nextcloud.service" - ]; - wantedBy = [ "multi-user.target" ]; - environment = { - NEXTCLOUD_URL = cfg.nextcloudUrl; - SOCKET_PATH = cfg.socketPath; - DATABASE_PREFIX = cfg.dbtableprefix; - LOG = cfg.logLevel; + systemd.services = { + nextcloud-notify_push = { + description = "Push daemon for Nextcloud clients"; + documentation = [ "https://github.com/nextcloud/notify_push" ]; + after = [ + "phpfpm-nextcloud.service" + "redis-nextcloud.service" + ]; + wantedBy = [ "multi-user.target" ]; + environment = { + NEXTCLOUD_URL = cfg.nextcloudUrl; + SOCKET_PATH = cfg.socketPath; + DATABASE_PREFIX = cfg.dbtableprefix; + LOG = cfg.logLevel; + }; + script = + let + dbType = if cfg.dbtype == "pgsql" then "postgresql" else cfg.dbtype; + dbUser = lib.optionalString (cfg.dbuser != null) cfg.dbuser; + dbPass = lib.optionalString (cfg.dbpassFile != null) ":$DATABASE_PASSWORD"; + dbHostHasPrefix = prefix: lib.hasPrefix prefix (toString cfg.dbhost); + isPostgresql = dbType == "postgresql"; + isMysql = dbType == "mysql"; + isSocket = (isPostgresql && dbHostHasPrefix "/") || (isMysql && dbHostHasPrefix "localhost:/"); + dbHost = lib.optionalString (cfg.dbhost != null) ( + if isSocket then lib.optionalString isMysql "@localhost" else "@${cfg.dbhost}" + ); + dbOpts = lib.optionalString (cfg.dbhost != null && isSocket) ( + if isPostgresql then + "?host=${cfg.dbhost}" + else if isMysql then + "?socket=${lib.removePrefix "localhost:" cfg.dbhost}" + else + throw "unsupported dbtype" + ); + dbName = lib.optionalString (cfg.dbname != null) "/${cfg.dbname}"; + dbUrl = "${dbType}://${dbUser}${dbPass}${dbHost}${dbName}${dbOpts}"; + in + lib.optionalString (cfg.dbpassFile != null) '' + export DATABASE_PASSWORD="$(<"$CREDENTIALS_DIRECTORY/dbpass")" + '' + + '' + export DATABASE_URL="${dbUrl}" + exec ${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php' + ''; + serviceConfig = { + User = "nextcloud"; + Group = "nextcloud"; + RuntimeDirectory = [ "nextcloud-notify_push" ]; + Restart = "on-failure"; + RestartSec = "5s"; + Type = "notify"; + LoadCredential = lib.optional (cfg.dbpassFile != null) "dbpass:${cfg.dbpassFile}"; + }; }; - postStart = '' - ${cfgN.occ}/bin/nextcloud-occ notify_push:setup ${cfg.nextcloudUrl}/push - ''; - script = - let - dbType = if cfg.dbtype == "pgsql" then "postgresql" else cfg.dbtype; - dbUser = lib.optionalString (cfg.dbuser != null) cfg.dbuser; - dbPass = lib.optionalString (cfg.dbpassFile != null) ":$DATABASE_PASSWORD"; - dbHostHasPrefix = prefix: lib.hasPrefix prefix (toString cfg.dbhost); - isPostgresql = dbType == "postgresql"; - isMysql = dbType == "mysql"; - isSocket = (isPostgresql && dbHostHasPrefix "/") || (isMysql && dbHostHasPrefix "localhost:/"); - dbHost = lib.optionalString (cfg.dbhost != null) ( - if isSocket then lib.optionalString isMysql "@localhost" else "@${cfg.dbhost}" - ); - dbOpts = lib.optionalString (cfg.dbhost != null && isSocket) ( - if isPostgresql then - "?host=${cfg.dbhost}" - else if isMysql then - "?socket=${lib.removePrefix "localhost:" cfg.dbhost}" - else - throw "unsupported dbtype" - ); - dbName = lib.optionalString (cfg.dbname != null) "/${cfg.dbname}"; - dbUrl = "${dbType}://${dbUser}${dbPass}${dbHost}${dbName}${dbOpts}"; - in - lib.optionalString (dbPass != "") '' - export DATABASE_PASSWORD="$(<"${cfg.dbpassFile}")" - '' - + '' - export DATABASE_URL="${dbUrl}" - exec ${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php' - ''; - serviceConfig = { - User = "nextcloud"; - Group = "nextcloud"; - RuntimeDirectory = [ "nextcloud-notify_push" ]; - Restart = "on-failure"; - RestartSec = "5s"; - Type = "notify"; + + nextcloud-notify_push_setup = { + wantedBy = [ "multi-user.target" ]; + requiredBy = [ "nextcloud-notify_push.service" ]; + after = [ "nextcloud-notify_push.service" ]; + serviceConfig = { + Type = "oneshot"; + User = "nextcloud"; + Group = "nextcloud"; + ExecStart = "${lib.getExe cfgN.occ} notify_push:setup ${cfg.nextcloudUrl}/push"; + LoadCredential = config.systemd.services.nextcloud-cron.serviceConfig.LoadCredential; + RestartMode = "direct"; + Restart = "on-failure"; + }; }; }; diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 1d3836b9c781..1943e06804a6 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -85,18 +85,60 @@ let "-dmemory_limit=${cfg.cli.memoryLimit}" ]); - occ = pkgs.writeScriptBin "nextcloud-occ" '' - #! ${pkgs.runtimeShell} - cd ${webroot} - sudo=exec - if [[ "$USER" != nextcloud ]]; then - sudo='exec /run/wrappers/bin/sudo -u nextcloud' - fi - $sudo ${pkgs.coreutils}/bin/env \ - NEXTCLOUD_CONFIG_DIR="${datadir}/config" \ - ${phpCli} \ - occ "$@" - ''; + # NOTE: The credentials required by all services at runtime, not including things like the + # admin password which is only needed by the setup service. + runtimeSystemdCredentials = [] + ++ (lib.optional (cfg.config.dbpassFile != null) "dbpass:${cfg.config.dbpassFile}") + ++ (lib.optional (cfg.config.objectstore.s3.enable) "s3_secret:${cfg.config.objectstore.s3.secretFile}") + ++ (lib.optional (cfg.config.objectstore.s3.sseCKeyFile != null) "s3_sse_c_key:${cfg.config.objectstore.s3.sseCKeyFile}"); + + requiresRuntimeSystemdCredentials = (lib.length runtimeSystemdCredentials) != 0; + + occ = pkgs.writeShellApplication { + name = "nextcloud-occ"; + + text = let + command = '' + ${lib.getExe' pkgs.coreutils "env"} \ + NEXTCLOUD_CONFIG_DIR="${datadir}/config" \ + ${phpCli} \ + occ "$@" + ''; + in '' + cd ${webroot} + + # NOTE: This is templated at eval time + requiresRuntimeSystemdCredentials=${lib.boolToString requiresRuntimeSystemdCredentials} + + # NOTE: This wrapper is both used in the internal nextcloud service units + # and by users outside a service context for administration. As such, + # when there's an existing CREDENTIALS_DIRECTORY, we inherit it for use + # in the nix_read_secret() php function. + # When there's no CREDENTIALS_DIRECTORY we try to use systemd-run to + # load the credentials just as in a service unit. + # NOTE: If there are no credentials that are required at runtime then there's no need + # to load any credentials. + if [[ $requiresRuntimeSystemdCredentials == true && -z "''${CREDENTIALS_DIRECTORY:-}" ]]; then + exec ${lib.getExe' config.systemd.package "systemd-run"} \ + ${lib.escapeShellArgs (map (credential: "--property=LoadCredential=${credential}") runtimeSystemdCredentials)} \ + --uid=nextcloud \ + --same-dir \ + --pty \ + --wait \ + --collect \ + --service-type=exec \ + --quiet \ + ${command} + elif [[ "$USER" != nextcloud ]]; then + exec /run/wrappers/bin/sudo \ + --preserve-env=CREDENTIALS_DIRECTORY \ + --user=nextcloud \ + ${command} + else + exec ${command} + fi + ''; + }; inherit (config.system) stateVersion; @@ -120,13 +162,13 @@ let 'bucket' => '${s3.bucket}', 'autocreate' => ${boolToString s3.autocreate}, 'key' => '${s3.key}', - 'secret' => nix_read_secret('${s3.secretFile}'), + 'secret' => nix_read_secret('s3_secret'), ${optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"} ${optionalString (s3.port != null) "'port' => ${toString s3.port},"} 'use_ssl' => ${boolToString s3.useSsl}, ${optionalString (s3.region != null) "'region' => '${s3.region}',"} 'use_path_style' => ${boolToString s3.usePathStyle}, - ${optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('${s3.sseCKeyFile}'),"} + ${optionalString (s3.sseCKeyFile != null) "'sse_c_key' => nix_read_secret('s3_sse_c_key'),"} ], ] ''; @@ -143,16 +185,26 @@ let in pkgs.writeText "nextcloud-config.php" '' '${c.dbhost}',"} ${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"} ${optionalString (c.dbtableprefix != null) "'dbtableprefix' => '${toString c.dbtableprefix}',"} - ${optionalString (c.dbpassFile != null) '' - 'dbpassword' => nix_read_secret( - "${c.dbpassFile}" - ), - '' - } + ${optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_secret('dbpass'),"} 'dbtype' => '${c.dbtype}', ${objectstoreConfig} ]; @@ -490,9 +537,8 @@ in { adminpassFile = mkOption { type = types.str; description = '' - The full path to a file that contains the admin's password. Must be - readable by user `nextcloud`. The password is set only in the initial - setup of Nextcloud by the systemd service `nextcloud-setup.service`. + The full path to a file that contains the admin's password. The password is + set only in the initial setup of Nextcloud by the systemd service `nextcloud-setup.service`. ''; }; objectstore = { @@ -530,8 +576,7 @@ in { type = types.str; example = "/var/nextcloud-objectstore-s3-secret"; description = '' - The full path to a file that contains the access secret. Must be - readable by user `nextcloud`. + The full path to a file that contains the access secret. ''; }; hostname = mkOption { @@ -592,8 +637,6 @@ in { openssl rand 32 | base64 ``` - Must be readable by user `nextcloud`. - [1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html ''; }; @@ -944,11 +987,6 @@ in { services.nextcloud.finalPackage = webroot; systemd.services = { - # When upgrading the Nextcloud package, Nextcloud can report errors such as - # "The files of the app [all apps in /var/lib/nextcloud/apps] were not replaced correctly" - # Restarting phpfpm on Nextcloud package update fixes these issues (but this is a workaround). - phpfpm-nextcloud.restartTriggers = [ webroot overrideConfig ]; - nextcloud-setup = let c = cfg.config; occInstallCmd = let @@ -959,12 +997,12 @@ in { dbpass = { arg = "DBPASS"; value = if c.dbpassFile != null - then ''"$(<"${toString c.dbpassFile}")"'' + then ''"$(<"$CREDENTIALS_DIRECTORY/dbpass")"'' else ''""''; }; adminpass = { arg = "ADMINPASS"; - value = ''"$(<"${toString c.adminpassFile}")"''; + value = ''"$(<"$CREDENTIALS_DIRECTORY/adminpass")"''; }; installFlags = concatStringsSep " \\\n " (mapAttrsToList (k: v: "${k} ${toString v}") { @@ -983,12 +1021,12 @@ in { in '' ${mkExport dbpass} ${mkExport adminpass} - ${occ}/bin/nextcloud-occ maintenance:install \ + ${lib.getExe occ} maintenance:install \ ${installFlags} ''; occSetTrustedDomainsCmd = concatStringsSep "\n" (imap0 (i: v: '' - ${occ}/bin/nextcloud-occ config:system:set trusted_domains \ + ${lib.getExe occ} config:system:set trusted_domains \ ${toString i} --value="${toString v}" '') ([ cfg.hostName ] ++ cfg.settings.trusted_domains)); @@ -1002,20 +1040,12 @@ in { restartTriggers = [ overrideConfig ]; script = '' ${optionalString (c.dbpassFile != null) '' - if [ ! -r "${c.dbpassFile}" ]; then - echo "dbpassFile ${c.dbpassFile} is not readable by nextcloud:nextcloud! Aborting..." - exit 1 - fi - if [ -z "$(<${c.dbpassFile})" ]; then + if [ -z "$(<$CREDENTIALS_DIRECTORY/dbpass)" ]; then echo "dbpassFile ${c.dbpassFile} is empty!" exit 1 fi ''} - if [ ! -r "${c.adminpassFile}" ]; then - echo "adminpassFile ${c.adminpassFile} is not readable by nextcloud:nextcloud! Aborting..." - exit 1 - fi - if [ -z "$(<${c.adminpassFile})" ]; then + if [ -z "$(<$CREDENTIALS_DIRECTORY/adminpass)" ]; then echo "adminpassFile ${c.adminpassFile} is empty!" exit 1 fi @@ -1032,57 +1062,102 @@ in { ${occInstallCmd} fi - ${occ}/bin/nextcloud-occ upgrade + ${lib.getExe occ} upgrade - ${occ}/bin/nextcloud-occ config:system:delete trusted_domains + ${lib.getExe occ} config:system:delete trusted_domains ${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) '' # Try to enable apps - ${occ}/bin/nextcloud-occ app:enable ${concatStringsSep " " (attrNames cfg.extraApps)} + ${lib.getExe occ} app:enable ${concatStringsSep " " (attrNames cfg.extraApps)} ''} ${occSetTrustedDomainsCmd} ''; serviceConfig.Type = "oneshot"; serviceConfig.User = "nextcloud"; + serviceConfig.LoadCredential = [ "adminpass:${cfg.config.adminpassFile}" ] ++ runtimeSystemdCredentials; # On Nextcloud ≥ 26, it is not necessary to patch the database files to prevent # an automatic creation of the database user. environment.NC_setup_create_db_user = lib.mkIf (nextcloudGreaterOrEqualThan "26") "false"; }; nextcloud-cron = { after = [ "nextcloud-setup.service" ]; + # NOTE: In contrast to the occ wrapper script running phpCli directly will not + # set NEXTCLOUD_CONFIG_DIR by itself currently. environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config"; + script = '' + # NOTE: This early returns the script when nextcloud is in maintenance mode + # or needs `occ upgrade`. Using ExecCondition= is not possible here + # because it doesn't work with systemd credentials. + if [[ $(${lib.getExe occ} status --output=json | ${lib.getExe pkgs.jq} '. | if .maintenance or .needsDbUpgrade then "skip" else "" end' --raw-output) == "skip" ]]; then + echo "Nextcloud is in maintenance mode or needs DB upgrade, exiting." + exit 0 + fi + + ${phpCli} -f ${webroot}/cron.php + ''; serviceConfig = { Type = "exec"; User = "nextcloud"; - ExecCondition = "${phpCli} -f ${webroot}/occ status -e"; - ExecStart = "${phpCli} -f ${webroot}/cron.php"; KillMode = "process"; + LoadCredential = runtimeSystemdCredentials; }; }; nextcloud-update-plugins = mkIf cfg.autoUpdateApps.enable { after = [ "nextcloud-setup.service" ]; serviceConfig = { Type = "oneshot"; - ExecStart = "${occ}/bin/nextcloud-occ app:update --all"; + ExecStart = "${lib.getExe occ} app:update --all"; User = "nextcloud"; + LoadCredential = runtimeSystemdCredentials; }; startAt = cfg.autoUpdateApps.startAt; }; nextcloud-update-db = { after = [ "nextcloud-setup.service" ]; - environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config"; script = '' - ${occ}/bin/nextcloud-occ db:add-missing-columns - ${occ}/bin/nextcloud-occ db:add-missing-indices - ${occ}/bin/nextcloud-occ db:add-missing-primary-keys + # NOTE: This early returns the script when nextcloud is in maintenance mode + # or needs `occ upgrade`. Using ExecCondition= is not possible here + # because it doesn't work with systemd credentials. + if [[ $(${lib.getExe occ} status --output=json | ${lib.getExe pkgs.jq} '. | if .maintenance or .needsDbUpgrade then "skip" else "" end' --raw-output) == "skip" ]]; then + echo "Nextcloud is in maintenance mode or needs DB upgrade, exiting." + exit 0 + fi + + ${lib.getExe occ} db:add-missing-columns + ${lib.getExe occ} db:add-missing-indices + ${lib.getExe occ} db:add-missing-primary-keys ''; serviceConfig = { Type = "exec"; User = "nextcloud"; - ExecCondition = "${phpCli} -f ${webroot}/occ status -e"; + LoadCredential = runtimeSystemdCredentials; }; }; + + phpfpm-nextcloud = { + # When upgrading the Nextcloud package, Nextcloud can report errors such as + # "The files of the app [all apps in /var/lib/nextcloud/apps] were not replaced correctly" + # Restarting phpfpm on Nextcloud package update fixes these issues (but this is a workaround). + restartTriggers = [ webroot overrideConfig ]; + } // lib.optionalAttrs requiresRuntimeSystemdCredentials { + serviceConfig.LoadCredential = runtimeSystemdCredentials; + + # FIXME: We use a hack to make the credential files readable by the nextcloud + # user by copying them somewhere else and overriding CREDENTIALS_DIRECTORY + # for php. This is currently necessary as the unit runs as root. + serviceConfig.RuntimeDirectory = lib.mkForce "phpfpm phpfpm-nextcloud"; + preStart = '' + umask 0077 + + # NOTE: Runtime directories for this service are currently preserved + # between restarts. + rm -rf /run/phpfpm-nextcloud/credentials/ + mkdir -p /run/phpfpm-nextcloud/credentials/ + cp "$CREDENTIALS_DIRECTORY"/* /run/phpfpm-nextcloud/credentials/ + chown -R nextcloud:nextcloud /run/phpfpm-nextcloud/credentials/ + ''; + }; }; services.phpfpm = { @@ -1091,6 +1166,7 @@ in { group = "nextcloud"; phpPackage = phpPackage; phpEnv = { + CREDENTIALS_DIRECTORY = "/run/phpfpm-nextcloud/credentials/"; NEXTCLOUD_CONFIG_DIR = "${datadir}/config"; PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"; }; diff --git a/nixos/tests/nextcloud/basic.nix b/nixos/tests/nextcloud/basic.nix index 217f22714c1c..9faf20a2f5ad 100644 --- a/nixos/tests/nextcloud/basic.nix +++ b/nixos/tests/nextcloud/basic.nix @@ -8,10 +8,10 @@ with import ../../lib/testing-python.nix { inherit system pkgs; }; runTest ( - { config, ... }: + { config, lib, ... }: { inherit name; - meta = with pkgs.lib.maintainers; { + meta = with lib.maintainers; { maintainers = [ globin eqyiel diff --git a/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix b/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix index 74343a22b7ae..40d231c21cac 100644 --- a/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix +++ b/nixos/tests/nextcloud/with-declarative-redis-and-secrets.nix @@ -8,13 +8,13 @@ with import ../../lib/testing-python.nix { inherit system pkgs; }; runTest ( - { config, ... }: + { config, lib, ... }: let inherit (config) adminuser; in { inherit name; - meta = with pkgs.lib.maintainers; { + meta = with lib.maintainers; { maintainers = [ eqyiel ma27 @@ -34,6 +34,13 @@ runTest ( redis = true; memcached = false; }; + notify_push = { + enable = true; + bendDomainToLocalhost = true; + logLevel = "debug"; + }; + extraAppsEnable = true; + extraApps.notify_push = config.services.nextcloud.package.packages.apps.notify_push; # This test also validates that we can use an "external" database database.createLocally = false; config = { @@ -70,7 +77,7 @@ runTest ( services.postgresql = { enable = true; }; - systemd.services.postgresql.postStart = pkgs.lib.mkAfter '' + systemd.services.postgresql.postStart = lib.mkAfter '' password=$(cat ${config.services.nextcloud.config.dbpassFile}) ${config.services.postgresql.package}/bin/psql <&2 &") + nextcloud.wait_until_succeeds("journalctl -u nextcloud-notify_push | grep -q \"Sending ping to ${config.adminuser}\"") ''; } ) diff --git a/nixos/tests/nextcloud/with-mysql-and-memcached.nix b/nixos/tests/nextcloud/with-mysql-and-memcached.nix index 110047fe6610..55b1e5e5695f 100644 --- a/nixos/tests/nextcloud/with-mysql-and-memcached.nix +++ b/nixos/tests/nextcloud/with-mysql-and-memcached.nix @@ -8,10 +8,10 @@ with import ../../lib/testing-python.nix { inherit system pkgs; }; runTest ( - { config, ... }: + { config, lib, ... }: { inherit name; - meta = with pkgs.lib.maintainers; { + meta = with lib.maintainers; { maintainers = [ eqyiel ]; }; diff --git a/nixos/tests/nextcloud/with-objectstore.nix b/nixos/tests/nextcloud/with-objectstore.nix index 5f24fc48851c..5a2a4a6fd0f1 100644 --- a/nixos/tests/nextcloud/with-objectstore.nix +++ b/nixos/tests/nextcloud/with-objectstore.nix @@ -20,7 +20,7 @@ runTest ( in { inherit name; - meta = with pkgs.lib.maintainers; { + meta = with lib.maintainers; { maintainers = [ onny ma27 diff --git a/nixos/tests/nextcloud/with-postgresql-and-redis.nix b/nixos/tests/nextcloud/with-postgresql-and-redis.nix index 17cdd38330a1..520aedf5688f 100644 --- a/nixos/tests/nextcloud/with-postgresql-and-redis.nix +++ b/nixos/tests/nextcloud/with-postgresql-and-redis.nix @@ -8,10 +8,10 @@ with import ../../lib/testing-python.nix { inherit system pkgs; }; runTest ( - { config, ... }: + { config, lib, ... }: { inherit name; - meta = with pkgs.lib.maintainers; { + meta = with lib.maintainers; { maintainers = [ eqyiel ma27 @@ -29,6 +29,7 @@ runTest ( ... }: { + environment.systemPackages = [ pkgs.jq ]; services.nextcloud = { caching = { apcu = false; @@ -68,12 +69,14 @@ runTest ( test-helpers.extraTests = '' with subtest("notify-push"): - client.execute("${pkgs.lib.getExe pkgs.nextcloud-notify_push.passthru.test_client} http://nextcloud ${config.adminuser} ${config.adminpass} >&2 &") + client.execute("${lib.getExe pkgs.nextcloud-notify_push.passthru.test_client} http://nextcloud ${config.adminuser} ${config.adminpass} >&2 &") nextcloud.wait_until_succeeds("journalctl -u nextcloud-notify_push | grep -q \"Sending ping to ${config.adminuser}\"") with subtest("Redis is used for caching"): # redis cache should not be empty - nextcloud.fail('test "[]" = "$(redis-cli --json KEYS "*")"') + assert nextcloud.succeed('redis-cli --json KEYS "*" | jq length').strip() != "0", """ + redis-cli for keys * returned 0 entries + """ with subtest("No code is returned when requesting PHP files (regression test)"): nextcloud.fail("curl -f http://nextcloud/nix-apps/notes/lib/AppInfo/Application.php")