diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 4d7f16b1e1a9..62ae763b69bc 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -6,6 +6,8 @@ let cfg = config.services.nextcloud; fpm = config.services.phpfpm.pools.nextcloud; + inherit (cfg) datadir; + phpPackage = cfg.phpPackage.buildEnv { extensions = { enabled, all }: (with all; @@ -40,7 +42,7 @@ let if [[ "$USER" != nextcloud ]]; then sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR --preserve-env=OC_PASS' fi - export NEXTCLOUD_CONFIG_DIR="${cfg.home}/config" + export NEXTCLOUD_CONFIG_DIR="${datadir}/config" $sudo \ ${phpPackage}/bin/php \ occ "$@" @@ -85,6 +87,59 @@ in { default = "/var/lib/nextcloud"; description = "Storage path of nextcloud."; }; + datadir = mkOption { + type = types.str; + defaultText = "config.services.nextcloud.home"; + description = '' + Data storage path of nextcloud. Will be by default. + This folder will be populated with a config.php and data folder which contains the state of the instance (excl the database)."; + ''; + example = "/mnt/nextcloud-file"; + }; + extraApps = mkOption { + type = types.attrsOf types.package; + default = { }; + description = '' + Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp. + The appid must be identical to the "id" value in the apps appinfo/info.xml. + Using this will disable the appstore to prevent Nextcloud from updating these apps (see ). + ''; + example = literalExpression '' + { + maps = pkgs.fetchNextcloudApp { + name = "maps"; + sha256 = "007y80idqg6b6zk6kjxg4vgw0z8fsxs9lajnv49vv1zjy6jx2i1i"; + url = "https://github.com/nextcloud/maps/releases/download/v0.1.9/maps-0.1.9.tar.gz"; + version = "0.1.9"; + }; + phonetrack = pkgs.fetchNextcloudApp { + name = "phonetrack"; + sha256 = "0qf366vbahyl27p9mshfma1as4nvql6w75zy2zk5xwwbp343vsbc"; + url = "https://gitlab.com/eneiluj/phonetrack-oc/-/wikis/uploads/931aaaf8dca24bf31a7e169a83c17235/phonetrack-0.6.9.tar.gz"; + version = "0.6.9"; + }; + } + ''; + }; + extraAppsEnable = mkOption { + type = types.bool; + default = true; + description = '' + Automatically enable the apps in every time nextcloud starts. + If set to false, apps need to be enabled in the Nextcloud user interface or with nextcloud-occ app:enable. + ''; + }; + appstoreEnable = mkOption { + type = types.nullOr types.bool; + default = null; + example = true; + description = '' + Allow the installation of apps and app updates from the store. + Enabled by default unless there are packages in . + Set to true to force enable the store even if is used. + Set to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting. + ''; + }; logLevel = mkOption { type = types.ints.between 0 4; default = 2; @@ -524,6 +579,8 @@ in { else nextcloud22 ); + services.nextcloud.datadir = mkOptionDefault config.services.nextcloud.home; + services.nextcloud.phpPackage = if versionOlder cfg.package.version "21" then pkgs.php74 else pkgs.php80; @@ -563,6 +620,14 @@ in { ] ''; + showAppStoreSetting = cfg.appstoreEnable != null || cfg.extraApps != {}; + renderedAppStoreSetting = + let + x = cfg.appstoreEnable; + in + if x == null then "false" + else boolToString x; + overrideConfig = pkgs.writeText "nextcloud-config.php" '' [ + ${optionalString (cfg.extraApps != { }) "[ 'path' => '${cfg.home}/nix-apps', 'url' => '/nix-apps', 'writable' => false ],"} [ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ], [ 'path' => '${cfg.home}/store-apps', 'url' => '/store-apps', 'writable' => true ], ], - 'datadirectory' => '${cfg.home}/data', + ${optionalString (showAppStoreSetting) "'appstoreenabled' => ${renderedAppStoreSetting},"} + 'datadirectory' => '${datadir}/data', 'skeletondirectory' => '${cfg.skeletonDirectory}', ${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"} 'log_type' => 'syslog', @@ -628,7 +695,7 @@ in { "--database-pass" = "\$${dbpass.arg}"; "--admin-user" = ''"${c.adminuser}"''; "--admin-pass" = "\$${adminpass.arg}"; - "--data-dir" = ''"${cfg.home}/data"''; + "--data-dir" = ''"${datadir}/data"''; }); in '' ${mkExport dbpass} @@ -670,9 +737,15 @@ in { ln -sf ${cfg.package}/apps ${cfg.home}/ + # Install extra apps + ln -sfT \ + ${pkgs.linkFarm "nix-apps" + (mapAttrsToList (name: path: { inherit name path; }) cfg.extraApps)} \ + ${cfg.home}/nix-apps + # create nextcloud directories. # if the directories exist already with wrong permissions, we fix that - for dir in ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps; do + for dir in ${datadir}/config ${datadir}/data ${cfg.home}/store-apps ${cfg.home}/nix-apps; do if [ ! -e $dir ]; then install -o nextcloud -g nextcloud -d $dir elif [ $(stat -c "%G" $dir) != "nextcloud" ]; then @@ -680,23 +753,29 @@ in { fi done - ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php + ln -sf ${overrideConfig} ${datadir}/config/override.config.php # Do not install if already installed - if [[ ! -e ${cfg.home}/config/config.php ]]; then + if [[ ! -e ${datadir}/config/config.php ]]; then ${occInstallCmd} fi ${occ}/bin/nextcloud-occ upgrade ${occ}/bin/nextcloud-occ config:system:delete trusted_domains + + ${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) '' + # Try to enable apps (don't fail when one of them cannot be enabled , eg. due to incompatible version) + ${occ}/bin/nextcloud-occ app:enable ${concatStringsSep " " (attrNames cfg.extraApps)} + ''} + ${occSetTrustedDomainsCmd} ''; serviceConfig.Type = "oneshot"; serviceConfig.User = "nextcloud"; }; nextcloud-cron = { - environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config"; + environment.NEXTCLOUD_CONFIG_DIR = "${datadir}/config"; serviceConfig.Type = "oneshot"; serviceConfig.User = "nextcloud"; serviceConfig.ExecStart = "${phpPackage}/bin/php -f ${cfg.package}/cron.php"; @@ -715,7 +794,7 @@ in { group = "nextcloud"; phpPackage = phpPackage; phpEnv = { - NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config"; + NEXTCLOUD_CONFIG_DIR = "${datadir}/config"; PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin"; }; settings = mapAttrs (name: mkDefault) { @@ -765,6 +844,10 @@ in { priority = 201; extraConfig = "root ${cfg.home};"; }; + "~ ^/nix-apps" = { + priority = 201; + extraConfig = "root ${cfg.home};"; + }; "^~ /.well-known" = { priority = 210; extraConfig = '' diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml index ed84487d233a..9d9cb8dfb3f2 100644 --- a/nixos/modules/services/web-apps/nextcloud.xml +++ b/nixos/modules/services/web-apps/nextcloud.xml @@ -237,6 +237,12 @@ Some apps may require extra PHP extensions to be installed. This can be configured with the setting. + + + Alternatively, extra apps can also be declared with the setting. + When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps + that are managed by Nix. If you want automatic updates it is recommended that you use web interface to install apps. +
diff --git a/nixos/tests/nextcloud/basic.nix b/nixos/tests/nextcloud/basic.nix index 1a7b25d5a49e..eb37470a4c7b 100644 --- a/nixos/tests/nextcloud/basic.nix +++ b/nixos/tests/nextcloud/basic.nix @@ -33,8 +33,13 @@ in { in { networking.firewall.allowedTCPPorts = [ 80 ]; + systemd.tmpfiles.rules = [ + "d /var/lib/nextcloud-data 0750 nextcloud nginx - -" + ]; + services.nextcloud = { enable = true; + datadir = "/var/lib/nextcloud-data"; hostName = "nextcloud"; config = { # Don't inherit adminuser since "root" is supposed to be the default @@ -98,6 +103,7 @@ in { "${withRcloneEnv} ${copySharedFile}" ) client.wait_for_unit("multi-user.target") + nextcloud.succeed("test -f /var/lib/nextcloud-data/data/root/files/test-shared-file") client.succeed( "${withRcloneEnv} ${diffSharedFile}" ) diff --git a/pkgs/build-support/fetchnextcloudapp/default.nix b/pkgs/build-support/fetchnextcloudapp/default.nix new file mode 100644 index 000000000000..7fe5b35e2596 --- /dev/null +++ b/pkgs/build-support/fetchnextcloudapp/default.nix @@ -0,0 +1,37 @@ +{ stdenv, gnutar, findutils, fetchurl, ... }: +{ name +, url +, version +, sha256 +, patches ? [ ] +}: +stdenv.mkDerivation { + name = "nc-app-${name}"; + inherit version patches; + + src = fetchurl { + inherit url sha256; + }; + + nativeBuildInputs = [ + gnutar + findutils + ]; + + unpackPhase = '' + tar -xzpf $src + ''; + + installPhase = '' + approot="$(dirname $(dirname $(find -path '*/appinfo/info.xml' | head -n 1)))" + + if [ -d "$approot" ]; + then + mv "$approot/" $out + chmod -R a-w $out + else + echo "Could not find appinfo/info.xml" + exit 1; + fi + ''; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 3087a4729844..f3197712d39a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -520,6 +520,8 @@ with pkgs; tests = callPackages ../build-support/fetchfirefoxaddon/tests.nix { }; }; + fetchNextcloudApp = callPackage ../build-support/fetchnextcloudapp {}; + # `fetchurl' downloads a file from the network. fetchurl = if stdenv.buildPlatform != stdenv.hostPlatform then buildPackages.fetchurl # No need to do special overrides twice,