Change:
Currently, the nextcloud modules has a set list of config options (in ), and no -style hook for freeform text which should be appended to nextcloud's configuration file. In particular, I am unable to figure out how to set up redis caching with the nextcloud module — the description for states that "you still need to enable Redis in your ", but there is no description of how to do that, and no corresponding option in the module. I think the module should offer something like , particular since this is probably also an issue for other possible configurations of nextcloud (given that its is prohibitively long) — or am I just missing something obvious?
I started a pull request with this here:
I marked this as stale due to inactivity. &rarr;
Same problem ;(

Discussion:
cfg = config.services.nextcloud; fpm = config.services.phpfpm.pools.nextcloud; <ins> jsonFormat = pkgs.formats.json {}; </ins> phpPackage = pkgs.php74.buildEnv { extensions = { enabled, all }: (with all;

The nextcloud-occ program preconfigured to target this Nextcloud instance. ''; }; <ins> extraOptions = mkOption { type = jsonFormat.type; default = {}; description = '' Extra options which should be appended to nextcloud's config.php file. ''; example = literalExample '' { redis = { host = "/run/redis/redis.sock"; port = 0; dbindex = 0; password = "secret"; timeout = 1.5; }; } ''; }; secretFile = mkOption { type = types.nullOr types.str; default = null; description = '' Secret options which will be appended to nextcloud's config.php file (written as JSON, in the same form as the <xref linkend="opt-services.nextcloud.extraOptions"/> option), for example <programlisting>{"redis":{"password":"secret"}}</programlisting>. ''; }; </ins> }; config = mkIf cfg.enable (mkMerge [

writePhpArrary = a: "[${concatMapStringsSep "," (val: ''"${toString val}"'') a}]"; overrideConfig = pkgs.writeText "nextcloud-config.php" '' <?php <del> ${optionalString (c.dbpassFile != null) '' function nix_read_pwd() { $file = "${c.dbpassFile}"; </del> <ins> ${optionalString (cfg.secretFile != null || c.dbpassFile != null) '' function nix_read_file($file, $error) { </ins> if (!file_exists($file)) { <del> throw new RuntimeException(sprintf( "Cannot start Nextcloud, dbpass file %s set by NixOS doesn't seem to " . "exist! Please make sure that the file exists and has appropriate " . "permissions for user & group 'nextcloud'!", $file )); </del> <ins> throw new RuntimeException(sprintf($error, $file)); </ins> } return trim(file_get_contents($file)); <ins> }''} function nix_decode_json_file($file, $error) { if (!file_exists($file)) { throw new RuntimeException(sprintf($error, $file)); </ins> } <del> ''} </del> <ins> $decoded = json_decode(file_get_contents($file), true); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException(sprintf("Cannot decode %s, because: %s", $file, json_last_error_msg())); } return $decoded; } </ins> $CONFIG = [ 'apps_paths' => [ [ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ],

${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"} ${optionalString (c.dbtableprefix != null) "'dbtableprefix' => '${toString c.dbtableprefix}',"} ${optionalString (c.dbpass != null) "'dbpassword' => '${c.dbpass}',"} <del> ${optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_pwd(),"} </del> <ins> ${optionalString (c.dbpassFile != null) '' dbpassword' => nix_read_file( ${c.dbpassFile}, "Cannot start Nextcloud, dbpass file %s set by NixOS doesn't seem to " . "exist! Please make sure that the file exists and has appropriate " . "permissions for user & group 'nextcloud'!" ), '' } </ins> 'dbtype' => '${c.dbtype}', 'trusted_domains' => ${writePhpArrary ([ cfg.hostName ] ++ c.extraTrustedDomains)}, 'trusted_proxies' => ${writePhpArrary (c.trustedProxies)}, ${optionalString (c.defaultPhoneRegion != null) "'default_phone_region' => '${c.defaultPhoneRegion}',"} ]; <ins> $EXTRACONFIG = nix_decode_json_file( "${jsonFormat.generate "nextcloud-extraOptions.json" cfg.extraOptions}", "decoding json extra options file failed" ); $CONFIG = array_replace_recursive($CONFIG, $EXTRACONFIG); ${optionalString (cfg.secretFile != null) '' $CONFIG = array_replace_recursive($CONFIG, nix_decode_json_file( "${cfg.secretFile}", "Cannot start Nextcloud, secrets file %s set by NixOS doesn't exist!" )); ''} </ins> ''; occInstallCmd = let dbpass = if c.dbpassFile != null

basic = import ./basic.nix { inherit system pkgs; }; with-postgresql-and-redis = import ./with-postgresql-and-redis.nix { inherit system pkgs; }; with-mysql-and-memcached = import ./with-mysql-and-memcached.nix { inherit system pkgs; }; <ins> with-declarative-redis = import ./with-declarative-redis.nix {inherit system pkgs; }; with-secrets = import ./with-secrets.nix {inherit system pkgs; }; </ins> }

<ins> import ../make-test-python.nix ({ pkgs, ...}: let adminpass = "hunter2"; adminuser = "custom-admin-username"; in { name = "nextcloud-with-declarative-redis"; meta = with pkgs.lib.maintainers; { maintainers = [ eqyiel ]; }; nodes = { # The only thing the client needs to do is download a file. client = { ... }: {}; nextcloud = { config, pkgs, ... }: { networking.firewall.allowedTCPPorts = [ 80 ]; services.nextcloud = { enable = true; hostName = "nextcloud"; caching = { apcu = false; redis = true; memcached = false; }; config = { dbtype = "pgsql"; dbname = "nextcloud"; dbuser = "nextcloud"; dbhost = "/run/postgresql"; inherit adminuser; adminpassFile = toString (pkgs.writeText "admin-pass-file" '' ${adminpass} ''); }; extraOptions.redis = { host = "/run/redis/redis.sock"; port = 0; dbindex = 0; password = "secret"; timeout = 1.5; }; extraOptions.memcache = { local = "OCMemcacheRedis"; locking = "OCMemcacheRedis"; }; }; services.redis = { enable = true; }; systemd.services.nextcloud-setup= { requires = ["postgresql.service"]; after = [ "postgresql.service" ]; }; services.postgresql = { enable = true; ensureDatabases = [ "nextcloud" ]; ensureUsers = [ { name = "nextcloud"; ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; } ]; }; }; }; testScript = let withRcloneEnv = pkgs.writeScript "with-rclone-env" '' #!${pkgs.runtimeShell} export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/" export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud" export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}" export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})" "''${@}" ''; copySharedFile = pkgs.writeScript "copy-shared-file" '' #!${pkgs.runtimeShell} echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file ''; diffSharedFile = pkgs.writeScript "diff-shared-file" '' #!${pkgs.runtimeShell} diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; in '' start_all() nextcloud.wait_for_unit("multi-user.target") nextcloud.succeed("curl -sSf http://nextcloud/login") nextcloud.succeed( "${withRcloneEnv} ${copySharedFile}" ) client.wait_for_unit("multi-user.target") client.succeed( "${withRcloneEnv} ${diffSharedFile}" ) # redis cache should not be empty nextcloud.fail("redis-cli KEYS * | grep -q 'empty array'") ''; }) </ins>

<ins> import ../make-test-python.nix ({ pkgs, ...}: let adminpass = "hunter2"; adminuser = "custom-admin-username"; in { name = "nextcloud-with-secrets-file"; meta = with pkgs.lib.maintainers; { maintainers = [ eqyiel ]; }; nodes = { # The only thing the client needs to do is download a file. client = { ... }: {}; nextcloud = { config, pkgs, ... }: { networking.firewall.allowedTCPPorts = [ 80 ]; services.nextcloud = { enable = true; hostName = "nextcloud"; caching = { apcu = false; memcached = false; }; config = { #dbtype = "pgsql"; dbname = "nextcloud"; dbuser = "nextcloud"; dbhost = "/run/postgresql"; inherit adminuser; adminpassFile = toString (pkgs.writeText "admin-pass-file" '' ${adminpass} ''); }; }; systemd.services.nextcloud-setup= { requires = ["postgresql.service"]; after = [ "postgresql.service" ]; }; services.postgresql = { enable = true; ensureDatabases = [ "nextcloud" ]; ensureUsers = [ { name = "nextcloud"; ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; } ]; }; # This file is meant to contain secret options which should # not go into the nix store. Here it is just used to set the # databyse type to postgres. environment.etc."nextcloud-secrets.json".text = '' { "dbtype" : "pgsql" } ''; }; }; testScript = let withRcloneEnv = pkgs.writeScript "with-rclone-env" '' #!${pkgs.runtimeShell} export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/" export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud" export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}" export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})" "''${@}" ''; copySharedFile = pkgs.writeScript "copy-shared-file" '' #!${pkgs.runtimeShell} echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file ''; diffSharedFile = pkgs.writeScript "diff-shared-file" '' #!${pkgs.runtimeShell} diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; in '' start_all() nextcloud.wait_for_unit("multi-user.target") nextcloud.succeed("curl -sSf http://nextcloud/login") nextcloud.succeed( "${withRcloneEnv} ${copySharedFile}" ) client.wait_for_unit("multi-user.target") client.succeed( "${withRcloneEnv} ${diffSharedFile}" ) ''; }) </ins>