Skip to content

Commit 109166f

Browse files
committed
nextcloud26: init at 26.0.0
1 parent 0b0cc27 commit 109166f

3 files changed

Lines changed: 163 additions & 1 deletion

File tree

pkgs/servers/nextcloud/default.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ in {
6060
sha256 = "sha256-wyUeAIOpQwPi1piLNS87Mwgqeacmsw/3RnCbD+hpoaY=";
6161
};
6262

63+
nextcloud26 = generic {
64+
version = "26.0.0";
65+
sha256 = "sha256-8WMVA2Ou6TZuy1zVJZv2dW7U8HPOp4tfpRXK2noNDD0=";
66+
};
67+
6368
# tip: get the sha with:
6469
# curl 'https://download.nextcloud.com/server/releases/nextcloud-${version}.tar.bz2.sha256'
6570
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
From 2e32658e52e196ef2e3ef671606da9131f0079d9 Mon Sep 17 00:00:00 2001
2+
From: Raito Bezarius <masterancpp@gmail.com>
3+
Date: Tue, 21 Mar 2023 16:38:29 +0100
4+
Subject: [PATCH] Setup: remove custom dbuser creation behavior
5+
6+
Both PostgreSQL and MySQL can be authenticated against from Nextcloud by
7+
supplying a database password. Now, during setup the following things
8+
happen:
9+
10+
* When using postgres and the db user has elevated permissions, a new
11+
unprivileged db user is created and the settings `dbuser`/`dbpass` are
12+
altered in `config.php`.
13+
14+
* When using MySQL, the password is **always** regenerated since
15+
24.0.5/23.0.9[1].
16+
17+
I consider both cases problematic: the reason why people do configuration
18+
management is to have it as single source of truth! So, IMHO any
19+
application that silently alters config and thus causes deployed
20+
nodes to diverge from the configuration is harmful for that.
21+
22+
I guess it was sheer luck that it worked for so long in NixOS because
23+
nobody has apparently used password authentication with a privileged
24+
user to operate Nextcloud (which is a good thing in fact).
25+
26+
[1] https://github.com/nextcloud/server/pull/33513
27+
28+
Original-Author: Maximilian Bosch <maximilian@mbosch.me>
29+
---
30+
lib/private/Setup/MySQL.php | 61 +++-----------------------------
31+
lib/private/Setup/PostgreSQL.php | 39 --------------------
32+
2 files changed, 4 insertions(+), 96 deletions(-)
33+
34+
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
35+
index 50f566728a9..ce721415e30 100644
36+
--- a/lib/private/Setup/MySQL.php
37+
+++ b/lib/private/Setup/MySQL.php
38+
@@ -145,62 +145,9 @@ class MySQL extends AbstractDatabase {
39+
* @param IDBConnection $connection
40+
*/
41+
private function createSpecificUser($username, $connection): void {
42+
- $rootUser = $this->dbUser;
43+
- $rootPassword = $this->dbPassword;
44+
-
45+
- //create a random password so we don't need to store the admin password in the config file
46+
- $saveSymbols = str_replace(['\"', '\\', '\'', '`'], '', ISecureRandom::CHAR_SYMBOLS);
47+
- $password = $this->random->generate(22, ISecureRandom::CHAR_ALPHANUMERIC . $saveSymbols)
48+
- . $this->random->generate(2, ISecureRandom::CHAR_UPPER)
49+
- . $this->random->generate(2, ISecureRandom::CHAR_LOWER)
50+
- . $this->random->generate(2, ISecureRandom::CHAR_DIGITS)
51+
- . $this->random->generate(2, $saveSymbols);
52+
- $this->dbPassword = str_shuffle($password);
53+
-
54+
- try {
55+
- //user already specified in config
56+
- $oldUser = $this->config->getValue('dbuser', false);
57+
-
58+
- //we don't have a dbuser specified in config
59+
- if ($this->dbUser !== $oldUser) {
60+
- //add prefix to the admin username to prevent collisions
61+
- $adminUser = substr('oc_' . $username, 0, 16);
62+
-
63+
- $i = 1;
64+
- while (true) {
65+
- //this should be enough to check for admin rights in mysql
66+
- $query = 'SELECT user FROM mysql.user WHERE user=?';
67+
- $result = $connection->executeQuery($query, [$adminUser]);
68+
-
69+
- //current dbuser has admin rights
70+
- $data = $result->fetchAll();
71+
- $result->closeCursor();
72+
- //new dbuser does not exist
73+
- if (count($data) === 0) {
74+
- //use the admin login data for the new database user
75+
- $this->dbUser = $adminUser;
76+
- $this->createDBUser($connection);
77+
-
78+
- break;
79+
- } else {
80+
- //repeat with different username
81+
- $length = strlen((string)$i);
82+
- $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i;
83+
- $i++;
84+
- }
85+
- }
86+
- } else {
87+
- // Reuse existing password if a database config is already present
88+
- $this->dbPassword = $rootPassword;
89+
- }
90+
- } catch (\Exception $ex) {
91+
- $this->logger->info('Can not create a new MySQL user, will continue with the provided user.', [
92+
- 'exception' => $ex,
93+
- 'app' => 'mysql.setup',
94+
- ]);
95+
- // Restore the original credentials
96+
- $this->dbUser = $rootUser;
97+
- $this->dbPassword = $rootPassword;
98+
- }
99+
+ $this->config->setValues([
100+
+ 'dbuser' => $this->dbUser,
101+
+ 'dbpassword' => $this->dbPassword,
102+
+ ]);
103+
}
104+
}
105+
diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php
106+
index 490cbba69a9..48e7f24f260 100644
107+
--- a/lib/private/Setup/PostgreSQL.php
108+
+++ b/lib/private/Setup/PostgreSQL.php
109+
@@ -45,45 +45,6 @@ class PostgreSQL extends AbstractDatabase {
110+
$connection = $this->connect([
111+
'dbname' => 'postgres'
112+
]);
113+
- if ($this->tryCreateDbUser) {
114+
- //check for roles creation rights in postgresql
115+
- $builder = $connection->getQueryBuilder();
116+
- $builder->automaticTablePrefix(false);
117+
- $query = $builder
118+
- ->select('rolname')
119+
- ->from('pg_roles')
120+
- ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE')))
121+
- ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
122+
-
123+
- try {
124+
- $result = $query->execute();
125+
- $canCreateRoles = $result->rowCount() > 0;
126+
- } catch (DatabaseException $e) {
127+
- $canCreateRoles = false;
128+
- }
129+
-
130+
- if ($canCreateRoles) {
131+
- $connectionMainDatabase = $this->connect();
132+
- //use the admin login data for the new database user
133+
-
134+
- //add prefix to the postgresql user name to prevent collisions
135+
- $this->dbUser = 'oc_' . strtolower($username);
136+
- //create a new password so we don't need to store the admin config in the config file
137+
- $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, ISecureRandom::CHAR_ALPHANUMERIC);
138+
-
139+
- $this->createDBUser($connection);
140+
-
141+
- // Go to the main database and grant create on the public schema
142+
- // The code below is implemented to make installing possible with PostgreSQL version 15:
143+
- // https://www.postgresql.org/docs/release/15.0/
144+
- // 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
145+
- // Therefore we assume that the database is only used by one user/service which is Nextcloud
146+
- // Additional services should get installed in a separate database in order to stay secure
147+
- // Also see https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PATTERNS
148+
- $connectionMainDatabase->executeQuery('GRANT CREATE ON SCHEMA public TO "' . addslashes($this->dbUser) . '"');
149+
- $connectionMainDatabase->close();
150+
- }
151+
- }
152+
153+
$this->config->setValues([
154+
'dbuser' => $this->dbUser,
155+
--
156+
2.39.2
157+

pkgs/top-level/all-packages.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10258,7 +10258,7 @@ with pkgs;
1025810258
grocy = callPackage ../servers/grocy { };
1025910259

1026010260
inherit (callPackage ../servers/nextcloud {})
10261-
nextcloud23 nextcloud24 nextcloud25;
10261+
nextcloud23 nextcloud24 nextcloud25 nextcloud26;
1026210262

1026310263
nextcloud23Packages = ( callPackage ../servers/nextcloud/packages {
1026410264
apps = lib.importJSON ../servers/nextcloud/packages/23.json;

0 commit comments

Comments
 (0)