summary refs log tree commit diff
diff options
context:
space:
mode:
authorColin Arnott <colin@urandom.co.uk>2023-01-27 07:14:38 +0000
committerColin Arnott <colin@urandom.co.uk>2023-01-27 15:28:41 +0000
commitaefbc9623b7855bb4a64ea874350d078925912be (patch)
treebca0047f2e5821da0d37ee34431f97550a3d0e5f
parent6173948c03942a3eaff2e18c7375f4f79c3b1739 (diff)
downloadnixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar.gz
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar.bz2
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar.lz
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar.xz
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.tar.zst
nixpkgs-aefbc9623b7855bb4a64ea874350d078925912be.zip
nextcloud26: init at 26.0.0beta1
Because nextcloud ships their prerelease versions on a different url, we
are not parsing the version string to detect which path to use. We also
enabled and validated this change via nixos module testing.
-rw-r--r--nixos/tests/nextcloud/default.nix2
-rw-r--r--pkgs/servers/nextcloud/default.nix20
-rw-r--r--pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch149
-rw-r--r--pkgs/top-level/all-packages.nix2
4 files changed, 164 insertions, 9 deletions
diff --git a/nixos/tests/nextcloud/default.nix b/nixos/tests/nextcloud/default.nix
index b8d3ba75b51..350486e8c73 100644
--- a/nixos/tests/nextcloud/default.nix
+++ b/nixos/tests/nextcloud/default.nix
@@ -26,4 +26,4 @@ foldl
     };
   })
 { }
-  [ 24 25 ]
+  [ 24 25 26 ]
diff --git a/pkgs/servers/nextcloud/default.nix b/pkgs/servers/nextcloud/default.nix
index 391644379ef..29edb77fabd 100644
--- a/pkgs/servers/nextcloud/default.nix
+++ b/pkgs/servers/nextcloud/default.nix
@@ -2,17 +2,18 @@
 
 let
   generic = {
-    version, sha256,
+    version, hash,
     eol ? false, extraVulnerabilities ? []
   }: let
     major = lib.versions.major version;
+    prerelease = builtins.length (lib.versions.splitVersion version) > 3;
   in stdenv.mkDerivation rec {
     pname = "nextcloud";
     inherit version;
 
     src = fetchurl {
-      url = "https://download.nextcloud.com/server/releases/${pname}-${version}.tar.bz2";
-      inherit sha256;
+      url = "https://download.nextcloud.com/server/${if prerelease then "prereleases" else "release"}/${pname}-${version}.tar.bz2";
+      inherit hash;
     };
 
     patches = [ (./patches + "/v${major}/0001-Setup-remove-custom-dbuser-creation-behavior.patch") ];
@@ -51,14 +52,19 @@ in {
 
   nextcloud24 = generic {
     version = "24.0.9";
-    sha256 = "580a3384c9c09aefb8e9b41553d21a6e20001799549dbd25b31dea211d97dd1e";
+    hash = "sha256-WAozhMnAmu+46bQVU9IabiAAF5lUnb0lsx3qIR2X3R4=";
   };
 
   nextcloud25 = generic {
     version = "25.0.3";
-    sha256 = "4b2b1423736ef92469096fe24f61c24cad87a34e07c1c7a81b385d3ea25c00ec";
+    hash = "sha256-SysUI3Nu+SRpCW/iT2HCTK2Ho04HwceoGzhdPqJcAOw=";
   };
 
-  # tip: get the sha with:
-  # curl 'https://download.nextcloud.com/server/releases/nextcloud-${version}.tar.bz2.sha256'
+  nextcloud26 = generic {
+    version = "26.0.0beta1";
+    hash = "sha256-EfSfn0KjQzciHa3VcrDhGC/aZUw/KDjihXs+qVIcYX0=";
+  };
+
+  # tip: get hash with:
+  # nix hash to-sri --type sha256 $(curl https://download.nextcloud.com/server/releases/nextcloud-${version}.tar.bz2.sha256 | cut -d' ' -f1)
 }
diff --git a/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch b/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch
new file mode 100644
index 00000000000..28af5ec7658
--- /dev/null
+++ b/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch
@@ -0,0 +1,149 @@
+From fc3e14155b3c4300b691ab46579830e725457a54 Mon Sep 17 00:00:00 2001
+From: Maximilian Bosch <maximilian@mbosch.me>
+Date: Sat, 10 Sep 2022 15:18:05 +0200
+Subject: [PATCH] Setup: remove custom dbuser creation behavior
+
+Both PostgreSQL and MySQL can be authenticated against from Nextcloud by
+supplying a database password. Now, during setup the following things
+happen:
+
+* When using postgres and the db user has elevated permissions, a new
+  unprivileged db user is created and the settings `dbuser`/`dbpass` are
+  altered in `config.php`.
+
+* When using MySQL, the password is **always** regenerated since
+  24.0.5/23.0.9[1].
+
+I consider both cases problematic: the reason why people do configuration
+management is to have it as single source of truth! So, IMHO any
+application that silently alters config and thus causes deployed
+nodes to diverge from the configuration is harmful for that.
+
+I guess it was sheer luck that it worked for so long in NixOS because
+nobody has apparently used password authentication with a privileged
+user to operate Nextcloud (which is a good thing in fact).
+
+[1] https://github.com/nextcloud/server/pull/33513
+---
+ lib/private/Setup/MySQL.php      | 53 --------------------------------
+ lib/private/Setup/PostgreSQL.php | 37 ----------------------
+ 2 files changed, 90 deletions(-)
+
+diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
+index e3004c269bc..bc958e84e44 100644
+--- a/lib/private/Setup/MySQL.php
++++ b/lib/private/Setup/MySQL.php
+@@ -141,62 +141,6 @@
+ 		$rootUser = $this->dbUser;
+ 		$rootPassword = $this->dbPassword;
+ 
+-		//create a random password so we don't need to store the admin password in the config file
+-		$saveSymbols = str_replace(['\"', '\\', '\'', '`'], '', ISecureRandom::CHAR_SYMBOLS);
+-		$password = $this->random->generate(22, ISecureRandom::CHAR_ALPHANUMERIC . $saveSymbols)
+-			. $this->random->generate(2, ISecureRandom::CHAR_UPPER)
+-			. $this->random->generate(2, ISecureRandom::CHAR_LOWER)
+-			. $this->random->generate(2, ISecureRandom::CHAR_DIGITS)
+-			. $this->random->generate(2, $saveSymbols)
+-		;
+-		$this->dbPassword = str_shuffle($password);
+-
+-		try {
+-			//user already specified in config
+-			$oldUser = $this->config->getValue('dbuser', false);
+-
+-			//we don't have a dbuser specified in config
+-			if ($this->dbUser !== $oldUser) {
+-				//add prefix to the admin username to prevent collisions
+-				$adminUser = substr('oc_' . $username, 0, 16);
+-
+-				$i = 1;
+-				while (true) {
+-					//this should be enough to check for admin rights in mysql
+-					$query = 'SELECT user FROM mysql.user WHERE user=?';
+-					$result = $connection->executeQuery($query, [$adminUser]);
+-
+-					//current dbuser has admin rights
+-					$data = $result->fetchAll();
+-					$result->closeCursor();
+-					//new dbuser does not exist
+-					if (count($data) === 0) {
+-						//use the admin login data for the new database user
+-						$this->dbUser = $adminUser;
+-						$this->createDBUser($connection);
+-
+-						break;
+-					} else {
+-						//repeat with different username
+-						$length = strlen((string)$i);
+-						$adminUser = substr('oc_' . $username, 0, 16 - $length) . $i;
+-						$i++;
+-					}
+-				}
+-			} else {
+-				// Reuse existing password if a database config is already present
+-				$this->dbPassword = $rootPassword;
+-			}
+-		} catch (\Exception $ex) {
+-			$this->logger->info('Can not create a new MySQL user, will continue with the provided user.', [
+-				'exception' => $ex,
+-				'app' => 'mysql.setup',
+-			]);
+-			// Restore the original credentials
+-			$this->dbUser = $rootUser;
+-			$this->dbPassword = $rootPassword;
+-		}
+-
+ 		$this->config->setValues([
+ 			'dbuser' => $this->dbUser,
+ 			'dbpassword' => $this->dbPassword,
+diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php
+index af816c7ad04..e49e5508e15 100644
+--- a/lib/private/Setup/PostgreSQL.php
++++ b/lib/private/Setup/PostgreSQL.php
+@@ -45,43 +45,6 @@ class PostgreSQL extends AbstractDatabase {
+ 			$connection = $this->connect([
+ 				'dbname' => 'postgres'
+ 			]);
+-			//check for roles creation rights in postgresql
+-			$builder = $connection->getQueryBuilder();
+-			$builder->automaticTablePrefix(false);
+-			$query = $builder
+-				->select('rolname')
+-				->from('pg_roles')
+-				->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE')))
+-				->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
+-
+-			try {
+-				$result = $query->execute();
+-				$canCreateRoles = $result->rowCount() > 0;
+-			} catch (DatabaseException $e) {
+-				$canCreateRoles = false;
+-			}
+-
+-			if ($canCreateRoles) {
+-				$connectionMainDatabase = $this->connect();
+-				//use the admin login data for the new database user
+-
+-				//add prefix to the postgresql user name to prevent collisions
+-				$this->dbUser = 'oc_' . strtolower($username);
+-				//create a new password so we don't need to store the admin config in the config file
+-				$this->dbPassword = \OC::$server->getSecureRandom()->generate(30, ISecureRandom::CHAR_ALPHANUMERIC);
+-
+-				$this->createDBUser($connection);
+-
+-				// Go to the main database and grant create on the public schema
+-				// The code below is implemented to make installing possible with PostgreSQL version 15:
+-				// https://www.postgresql.org/docs/release/15.0/
+-				// From the release notes: For new databases having no need to defend against insider threats, granting CREATE permission will yield the behavior of prior releases
+-				// Therefore we assume that the database is only used by one user/service which is Nextcloud
+-				// Additional services should get installed in a separate database in order to stay secure
+-				// Also see https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PATTERNS
+-				$connectionMainDatabase->executeQuery('GRANT CREATE ON SCHEMA public TO ' . addslashes($this->dbUser));
+-				$connectionMainDatabase->close();
+-			}
+ 
+ 			$this->config->setValues([
+ 				'dbuser' => $this->dbUser,
+-- 
+2.38.1
+
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 1db83912c65..51574d82902 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -9960,7 +9960,7 @@ with pkgs;
   grocy = callPackage ../servers/grocy { };
 
   inherit (callPackage ../servers/nextcloud {})
-    nextcloud23 nextcloud24 nextcloud25;
+    nextcloud23 nextcloud24 nextcloud25 nextcloud26;
 
   nextcloud23Packages = ( callPackage ../servers/nextcloud/packages {
     apps = lib.importJSON ../servers/nextcloud/packages/23.json;