lol

Merge pull request #266270 from Ma27/postgresql-ownership-15

authored by

Ryan Lahfa and committed by
GitHub
ccfe07c3 bea932e0

+205 -132
+3
nixos/doc/manual/release-notes/rl-2311.section.md
··· 145 145 146 146 ## Backward Incompatibilities {#sec-release-23.11-incompatibilities} 147 147 148 + - `services.postgresql.ensurePermissions` has been deprecated in favor of `services.postgresql.ensureUsers.*.ensureDBOwnership` which simplifies the setup of database owned by a certain system user 149 + in local database contexts (which make use of peer authentication via UNIX sockets), migration guidelines were provided in the NixOS manual, please refer to them if you are affected by a PostgreSQL 15 changing the way `GRANT ALL PRIVILEGES` is working. `services.postgresql.ensurePermissions` will be removed in 24.05. All NixOS modules were migrated using one of the strategy, e.g. `ensureDBOwnership` or `postStart`. More about this situation can be learnt in https://github.com/NixOS/nixpkgs/pull/266270. 150 + 148 151 - `network-online.target` has been fixed to no longer time out for systems with `networking.useDHCP = true` and `networking.useNetworkd = true`. 149 152 Workarounds for this can be removed. 150 153
+47 -11
nixos/modules/services/databases/postgresql.nix
··· 168 168 ensurePermissions = mkOption { 169 169 type = types.attrsOf types.str; 170 170 default = {}; 171 + visible = false; # This option has been deprecated. 171 172 description = lib.mdDoc '' 173 + This option is DEPRECATED and should not be used in nixpkgs anymore, 174 + use `ensureDBOwnership` instead. It can also break with newer 175 + versions of PostgreSQL (≥ 15). 176 + 172 177 Permissions to ensure for the user, specified as an attribute set. 173 178 The attribute names specify the database and tables to grant the permissions for. 174 179 The attribute values specify the permissions to grant. You may specify one or ··· 184 189 "DATABASE \"nextcloud\"" = "ALL PRIVILEGES"; 185 190 "ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES"; 186 191 } 192 + ''; 193 + }; 194 + 195 + ensureDBOwnership = mkOption { 196 + type = types.bool; 197 + default = false; 198 + description = mdDoc '' 199 + Grants the user ownership to a database with the same name. 200 + This database must be defined manually in 201 + [](#opt-services.postgresql.ensureDatabases). 187 202 ''; 188 203 }; 189 204 ··· 338 353 }); 339 354 default = []; 340 355 description = lib.mdDoc '' 341 - Ensures that the specified users exist and have at least the ensured permissions. 356 + Ensures that the specified users exist. 342 357 The PostgreSQL users will be identified using peer authentication. This authenticates the Unix user with the 343 358 same name only, and that without the need for a password. 344 - This option will never delete existing users or remove permissions, especially not when the value of this 345 - option is changed. This means that users created and permissions assigned once through this option or 346 - otherwise have to be removed manually. 359 + This option will never delete existing users or remove DB ownership of databases 360 + once granted with `ensureDBOwnership = true;`. This means that this must be 361 + cleaned up manually when changing after changing the config in here. 347 362 ''; 348 363 example = literalExpression '' 349 364 [ 350 365 { 351 366 name = "nextcloud"; 352 - ensurePermissions = { 353 - "DATABASE nextcloud" = "ALL PRIVILEGES"; 354 - }; 355 367 } 356 368 { 357 369 name = "superuser"; 358 - ensurePermissions = { 359 - "ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES"; 360 - }; 370 + ensureDBOwnership = true; 361 371 } 362 372 ] 363 373 ''; ··· 445 455 446 456 config = mkIf cfg.enable { 447 457 458 + assertions = map ({ name, ensureDBOwnership, ... }: { 459 + assertion = ensureDBOwnership -> builtins.elem name cfg.ensureDatabases; 460 + message = '' 461 + For each database user defined with `services.postgresql.ensureUsers` and 462 + `ensureDBOwnership = true;`, a database with the same name must be defined 463 + in `services.postgresql.ensureDatabases`. 464 + 465 + Offender: ${name} has not been found among databases. 466 + ''; 467 + }) cfg.ensureUsers; 468 + # `ensurePermissions` is now deprecated, let's avoid it. 469 + warnings = lib.optional (any ({ ensurePermissions, ... }: ensurePermissions != {}) cfg.ensureUsers) " 470 + `services.postgresql.*.ensurePermissions` is used in your expressions, 471 + this option is known to be broken with newer PostgreSQL versions, 472 + consider migrating to `services.postgresql.*.ensureDBOwnership` or 473 + consult the release notes or manual for more migration guidelines. 474 + 475 + This option will be removed in NixOS 24.05 unless it sees significant 476 + maintenance improvements. 477 + "; 478 + 448 479 services.postgresql.settings = 449 480 { 450 481 hba_file = "${pkgs.writeText "pg_hba.conf" cfg.authentication}"; ··· 556 587 ${ 557 588 concatMapStrings 558 589 (user: 559 - let 590 + let 560 591 userPermissions = concatStringsSep "\n" 561 592 (mapAttrsToList 562 593 (database: permission: ''$PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"' '') 563 594 user.ensurePermissions 564 595 ); 596 + dbOwnershipStmt = optionalString 597 + user.ensureDBOwnership 598 + ''$PSQL -tAc 'ALTER DATABASE "${user.name}" OWNER TO "${user.name}";' ''; 565 599 566 600 filteredClauses = filterAttrs (name: value: value != null) user.ensureClauses; 567 601 ··· 572 606 $PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc 'CREATE USER "${user.name}"' 573 607 ${userPermissions} 574 608 ${userClauses} 609 + 610 + ${dbOwnershipStmt} 575 611 '' 576 612 ) 577 613 cfg.ensureUsers
+2 -2
nixos/modules/services/development/zammad.nix
··· 204 204 205 205 assertions = [ 206 206 { 207 - assertion = cfg.database.createLocally -> cfg.database.user == "zammad"; 207 + assertion = cfg.database.createLocally -> cfg.database.user == "zammad" && cfg.database.name == "zammad"; 208 208 message = "services.zammad.database.user must be set to \"zammad\" if services.zammad.database.createLocally is set to true"; 209 209 } 210 210 { ··· 231 231 ensureUsers = [ 232 232 { 233 233 name = cfg.database.user; 234 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 234 + ensureDBOwnership = true; 235 235 } 236 236 ]; 237 237 };
+1 -1
nixos/modules/services/finance/odoo.nix
··· 121 121 ensureDatabases = [ "odoo" ]; 122 122 ensureUsers = [{ 123 123 name = "odoo"; 124 - ensurePermissions = { "DATABASE odoo" = "ALL PRIVILEGES"; }; 124 + ensureDBOwnership = true; 125 125 }]; 126 126 }; 127 127 });
+1 -1
nixos/modules/services/mail/listmonk.nix
··· 168 168 169 169 ensureUsers = [{ 170 170 name = "listmonk"; 171 - ensurePermissions = { "DATABASE listmonk" = "ALL PRIVILEGES"; }; 171 + ensureDBOwnership = true; 172 172 }]; 173 173 174 174 ensureDatabases = [ "listmonk" ];
+11 -3
nixos/modules/services/mail/roundcube.nix
··· 179 179 }; 180 180 }; 181 181 182 + assertions = [ 183 + { 184 + assertion = localDB -> cfg.database.username == cfg.database.dbname; 185 + message = '' 186 + When setting up a DB and its owner user, the owner and the DB name must be 187 + equal! 188 + ''; 189 + } 190 + ]; 191 + 182 192 services.postgresql = mkIf localDB { 183 193 enable = true; 184 194 ensureDatabases = [ cfg.database.dbname ]; 185 195 ensureUsers = [ { 186 196 name = cfg.database.username; 187 - ensurePermissions = { 188 - "DATABASE ${cfg.database.username}" = "ALL PRIVILEGES"; 189 - }; 197 + ensureDBOwnership = true; 190 198 } ]; 191 199 }; 192 200
+4 -6
nixos/modules/services/mail/sympa.nix
··· 218 218 default = null; 219 219 example = "/run/keys/sympa-dbpassword"; 220 220 description = lib.mdDoc '' 221 - A file containing the password for {option}`services.sympa.database.user`. 221 + A file containing the password for {option}`services.sympa.database.name`. 222 222 ''; 223 223 }; 224 224 ··· 342 342 343 343 db_type = cfg.database.type; 344 344 db_name = cfg.database.name; 345 + db_user = cfg.database.name; 345 346 } 346 347 // (optionalAttrs (cfg.database.host != null) { 347 348 db_host = cfg.database.host; ··· 354 355 }) 355 356 // (optionalAttrs (cfg.database.port != null) { 356 357 db_port = cfg.database.port; 357 - }) 358 - // (optionalAttrs (cfg.database.user != null) { 359 - db_user = cfg.database.user; 360 358 }) 361 359 // (optionalAttrs (cfg.mta.type == "postfix") { 362 360 sendmail_aliases = "${dataDir}/sympa_transport"; ··· 393 391 users.groups.${group} = {}; 394 392 395 393 assertions = [ 396 - { assertion = cfg.database.createLocally -> cfg.database.user == user; 394 + { assertion = cfg.database.createLocally -> cfg.database.user == user && cfg.database.name == cfg.database.user; 397 395 message = "services.sympa.database.user must be set to ${user} if services.sympa.database.createLocally is set to true"; 398 396 } 399 397 { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; ··· 579 577 ensureDatabases = [ cfg.database.name ]; 580 578 ensureUsers = [ 581 579 { name = cfg.database.user; 582 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 580 + ensureDBOwnership = true; 583 581 } 584 582 ]; 585 583 };
+2 -2
nixos/modules/services/matrix/matrix-sliding-sync.nix
··· 74 74 services.postgresql = lib.optionalAttrs cfg.createDatabase { 75 75 enable = true; 76 76 ensureDatabases = [ "matrix-sliding-sync" ]; 77 - ensureUsers = [ rec { 77 + ensureUsers = [ { 78 78 name = "matrix-sliding-sync"; 79 - ensurePermissions."DATABASE \"${name}\"" = "ALL PRIVILEGES"; 79 + ensureDBOwnership = true; 80 80 } ]; 81 81 }; 82 82
+1 -3
nixos/modules/services/matrix/mautrix-facebook.nix
··· 135 135 ensureDatabases = ["mautrix-facebook"]; 136 136 ensureUsers = [{ 137 137 name = "mautrix-facebook"; 138 - ensurePermissions = { 139 - "DATABASE \"mautrix-facebook\"" = "ALL PRIVILEGES"; 140 - }; 138 + ensureDBOwnership = true; 141 139 }]; 142 140 }; 143 141
+1 -3
nixos/modules/services/misc/atuin.nix
··· 73 73 enable = true; 74 74 ensureUsers = [{ 75 75 name = "atuin"; 76 - ensurePermissions = { 77 - "DATABASE atuin" = "ALL PRIVILEGES"; 78 - }; 76 + ensureDBOwnership = true; 79 77 }]; 80 78 ensureDatabases = [ "atuin" ]; 81 79 };
+9 -1
nixos/modules/services/misc/forgejo.nix
··· 357 357 assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user; 358 358 message = "services.forgejo.database.user must match services.forgejo.user if the database is to be automatically provisioned"; 359 359 } 360 + { assertion = cfg.database.createDatabase && usePostgresql -> cfg.database.user == cfg.database.name; 361 + message = '' 362 + When creating a database via NixOS, the db user and db name must be equal! 363 + If you already have an existing DB+user and this assertion is new, you can safely set 364 + `services.forgejo.createDatabase` to `false` because removal of `ensureUsers` 365 + and `ensureDatabases` doesn't have any effect. 366 + ''; 367 + } 360 368 ]; 361 369 362 370 services.forgejo.settings = { ··· 423 431 ensureUsers = [ 424 432 { 425 433 name = cfg.database.user; 426 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 434 + ensureDBOwnership = true; 427 435 } 428 436 ]; 429 437 };
+9 -1
nixos/modules/services/misc/gitea.nix
··· 394 394 { assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user; 395 395 message = "services.gitea.database.user must match services.gitea.user if the database is to be automatically provisioned"; 396 396 } 397 + { assertion = cfg.database.createDatabase && usePostgresql -> cfg.database.user == cfg.database.name; 398 + message = '' 399 + When creating a database via NixOS, the db user and db name must be equal! 400 + If you already have an existing DB+user and this assertion is new, you can safely set 401 + `services.gitea.createDatabase` to `false` because removal of `ensureUsers` 402 + and `ensureDatabases` doesn't have any effect. 403 + ''; 404 + } 397 405 ]; 398 406 399 407 services.gitea.settings = { ··· 461 469 ensureDatabases = [ cfg.database.name ]; 462 470 ensureUsers = [ 463 471 { name = cfg.database.user; 464 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 472 + ensureDBOwnership = true; 465 473 } 466 474 ]; 467 475 };
+2 -2
nixos/modules/services/misc/redmine.nix
··· 267 267 { assertion = cfg.database.passwordFile != null || cfg.database.socket != null; 268 268 message = "one of services.redmine.database.socket or services.redmine.database.passwordFile must be set"; 269 269 } 270 - { assertion = cfg.database.createLocally -> cfg.database.user == cfg.user; 270 + { assertion = cfg.database.createLocally -> cfg.database.user == cfg.user && cfg.database.user == cfg.database.name; 271 271 message = "services.redmine.database.user must be set to ${cfg.user} if services.redmine.database.createLocally is set true"; 272 272 } 273 273 { assertion = cfg.database.createLocally -> cfg.database.socket != null; ··· 315 315 ensureDatabases = [ cfg.database.name ]; 316 316 ensureUsers = [ 317 317 { name = cfg.database.user; 318 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 318 + ensureDBOwnership = true; 319 319 } 320 320 ]; 321 321 };
+7 -3
nixos/modules/services/misc/sourcehut/service.nix
··· 249 249 ensureDatabases = [ srvCfg.postgresql.database ]; 250 250 ensureUsers = map (name: { 251 251 inherit name; 252 - ensurePermissions = { "DATABASE \"${srvCfg.postgresql.database}\"" = "ALL PRIVILEGES"; }; 252 + # We don't use it because we have a special default database name with dots. 253 + # TODO(for maintainers of sourcehut): migrate away from custom preStart script. 254 + ensureDBOwnership = false; 253 255 }) [srvCfg.user]; 254 256 }; 257 + 255 258 256 259 services.sourcehut.settings = mkMerge [ 257 260 { ··· 378 381 extraService 379 382 ])) extraServices) 380 383 381 - # Work around 'pq: permission denied for schema public' with postgres v15, until a 382 - # solution for `services.postgresql.ensureUsers` is found. 384 + # Work around 'pq: permission denied for schema public' with postgres v15. 383 385 # See https://github.com/NixOS/nixpkgs/issues/216989 384 386 # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741 387 + # TODO(to maintainers of sourcehut): please migrate away from this workaround 388 + # by migrating away from database name defaults with dots. 385 389 (lib.mkIf ( 386 390 cfg.postgresql.enable 387 391 && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0"
+2 -2
nixos/modules/services/monitoring/zabbix-proxy.nix
··· 203 203 { assertion = !config.services.zabbixServer.enable; 204 204 message = "Please choose one of services.zabbixServer or services.zabbixProxy."; 205 205 } 206 - { assertion = cfg.database.createLocally -> cfg.database.user == user; 206 + { assertion = cfg.database.createLocally -> cfg.database.user == user && cfg.database.name == cfg.database.user; 207 207 message = "services.zabbixProxy.database.user must be set to ${user} if services.zabbixProxy.database.createLocally is set true"; 208 208 } 209 209 { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; ··· 252 252 ensureDatabases = [ cfg.database.name ]; 253 253 ensureUsers = [ 254 254 { name = cfg.database.user; 255 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 255 + ensureDBOwnership = true; 256 256 } 257 257 ]; 258 258 };
+2 -2
nixos/modules/services/monitoring/zabbix-server.nix
··· 191 191 config = mkIf cfg.enable { 192 192 193 193 assertions = [ 194 - { assertion = cfg.database.createLocally -> cfg.database.user == user; 194 + { assertion = cfg.database.createLocally -> cfg.database.user == user && cfg.database.user == cfg.database.name; 195 195 message = "services.zabbixServer.database.user must be set to ${user} if services.zabbixServer.database.createLocally is set true"; 196 196 } 197 197 { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; ··· 240 240 ensureDatabases = [ cfg.database.name ]; 241 241 ensureUsers = [ 242 242 { name = cfg.database.user; 243 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 243 + ensureDBOwnership = true; 244 244 } 245 245 ]; 246 246 };
+1 -1
nixos/modules/services/security/hockeypuck.nix
··· 55 55 ensureDatabases = [ "hockeypuck" ]; 56 56 ensureUsers = [{ 57 57 name = "hockeypuck"; 58 - ensurePermissions."DATABASE hockeypuck" = "ALL PRIVILEGES"; 58 + ensureDBOwnership = true; 59 59 }]; 60 60 }; 61 61 ```
+4 -6
nixos/modules/services/web-apps/coder.nix
··· 149 149 150 150 config = mkIf cfg.enable { 151 151 assertions = [ 152 - { assertion = cfg.database.createLocally -> cfg.database.username == name; 153 - message = "services.coder.database.username must be set to ${user} if services.coder.database.createLocally is set true"; 152 + { assertion = cfg.database.createLocally -> cfg.database.username == name && cfg.database.database == cfg.database.username; 153 + message = "services.coder.database.username must be set to ${name} if services.coder.database.createLocally is set true"; 154 154 } 155 155 ]; 156 156 ··· 193 193 cfg.database.database 194 194 ]; 195 195 ensureUsers = [{ 196 - name = cfg.database.username; 197 - ensurePermissions = { 198 - "DATABASE \"${cfg.database.database}\"" = "ALL PRIVILEGES"; 199 - }; 196 + name = cfg.user; 197 + ensureDBOwnership = true; 200 198 } 201 199 ]; 202 200 };
+1 -3
nixos/modules/services/web-apps/gotosocial.nix
··· 128 128 ensureUsers = [ 129 129 { 130 130 name = "gotosocial"; 131 - ensurePermissions = { 132 - "DATABASE gotosocial" = "ALL PRIVILEGES"; 133 - }; 131 + ensureDBOwnership = true; 134 132 } 135 133 ]; 136 134 };
+9 -6
nixos/modules/services/web-apps/invidious.nix
··· 109 109 # Default to using the local database if we create it 110 110 services.invidious.database.host = lib.mkDefault null; 111 111 112 + 113 + # TODO(raitobezarius to maintainers of invidious): I strongly advise to clean up the kemal specific 114 + # thing for 24.05 and use `ensureDBOwnership`. 115 + # See https://github.com/NixOS/nixpkgs/issues/216989 116 + systemd.services.postgresql.postStart = lib.mkAfter '' 117 + $PSQL -tAc 'ALTER DATABASE "${cfg.settings.db.dbname}" OWNER TO "${cfg.settings.db.user}";' 118 + ''; 112 119 services.postgresql = { 113 120 enable = true; 121 + ensureUsers = lib.singleton { name = cfg.settings.db.user; ensureDBOwnership = false; }; 114 122 ensureDatabases = lib.singleton cfg.settings.db.dbname; 115 - ensureUsers = lib.singleton { 116 - name = cfg.settings.db.user; 117 - ensurePermissions = { 118 - "DATABASE ${cfg.settings.db.dbname}" = "ALL PRIVILEGES"; 119 - }; 120 - }; 121 123 # This is only needed because the unix user invidious isn't the same as 122 124 # the database user. This tells postgres to map one to the other. 123 125 identMap = '' ··· 136 138 documentation = [ "https://docs.invidious.io/Database-Information-and-Maintenance.md" ]; 137 139 startAt = lib.mkDefault "weekly"; 138 140 path = [ config.services.postgresql.package ]; 141 + after = [ "postgresql.service" ]; 139 142 script = '' 140 143 psql ${cfg.settings.db.dbname} ${cfg.settings.db.user} -c "DELETE FROM nonces * WHERE expire < current_timestamp" 141 144 psql ${cfg.settings.db.dbname} ${cfg.settings.db.user} -c "TRUNCATE TABLE videos"
+1 -1
nixos/modules/services/web-apps/lemmy.nix
··· 146 146 ensureDatabases = [ cfg.settings.database.database ]; 147 147 ensureUsers = [{ 148 148 name = cfg.settings.database.user; 149 - ensurePermissions."DATABASE ${cfg.settings.database.database}" = "ALL PRIVILEGES"; 149 + ensureDBOwnership = true; 150 150 }]; 151 151 }; 152 152
+3 -3
nixos/modules/services/web-apps/mastodon.nix
··· 612 612 config = lib.mkIf cfg.enable (lib.mkMerge [{ 613 613 assertions = [ 614 614 { 615 - assertion = databaseActuallyCreateLocally -> (cfg.user == cfg.database.user); 615 + assertion = databaseActuallyCreateLocally -> (cfg.user == cfg.database.user && cfg.database.user == cfg.database.name); 616 616 message = '' 617 617 For local automatic database provisioning (services.mastodon.database.createLocally == true) with peer 618 618 authentication (services.mastodon.database.host == "/run/postgresql") to work services.mastodon.user ··· 845 845 enable = true; 846 846 ensureUsers = [ 847 847 { 848 - name = cfg.database.user; 849 - ensurePermissions."DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; 848 + name = cfg.database.name; 849 + ensureDBOwnership = true; 850 850 } 851 851 ]; 852 852 ensureDatabases = [ cfg.database.name ];
+2 -2
nixos/modules/services/web-apps/mediawiki.nix
··· 454 454 { assertion = cfg.database.createLocally -> (cfg.database.type == "mysql" || cfg.database.type == "postgres"); 455 455 message = "services.mediawiki.createLocally is currently only supported for database type 'mysql' and 'postgres'"; 456 456 } 457 - { assertion = cfg.database.createLocally -> cfg.database.user == user; 457 + { assertion = cfg.database.createLocally -> cfg.database.user == user && cfg.database.name == cfg.database.user; 458 458 message = "services.mediawiki.database.user must be set to ${user} if services.mediawiki.database.createLocally is set true"; 459 459 } 460 460 { assertion = cfg.database.createLocally -> cfg.database.socket != null; ··· 486 486 ensureDatabases = [ cfg.database.name ]; 487 487 ensureUsers = [{ 488 488 name = cfg.database.user; 489 - ensurePermissions = { "DATABASE \"${cfg.database.name}\"" = "ALL PRIVILEGES"; }; 489 + ensureDBOwnership = true; 490 490 }]; 491 491 }; 492 492
+6 -11
nixos/modules/services/web-apps/miniflux.nix
··· 6 6 7 7 defaultAddress = "localhost:8080"; 8 8 9 - dbUser = "miniflux"; 10 - dbName = "miniflux"; 11 - 12 9 pgbin = "${config.services.postgresql.package}/bin"; 13 10 preStart = pkgs.writeScript "miniflux-pre-start" '' 14 11 #!${pkgs.runtimeShell} 15 - ${pgbin}/psql "${dbName}" -c "CREATE EXTENSION IF NOT EXISTS hstore" 12 + ${pgbin}/psql "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore" 16 13 ''; 17 14 in 18 15 ··· 62 59 63 60 services.miniflux.config = { 64 61 LISTEN_ADDR = mkDefault defaultAddress; 65 - DATABASE_URL = "user=${dbUser} host=/run/postgresql dbname=${dbName}"; 62 + DATABASE_URL = "user=miniflux host=/run/postgresql dbname=miniflux"; 66 63 RUN_MIGRATIONS = "1"; 67 64 CREATE_ADMIN = "1"; 68 65 }; ··· 70 67 services.postgresql = { 71 68 enable = true; 72 69 ensureUsers = [ { 73 - name = dbUser; 74 - ensurePermissions = { 75 - "DATABASE ${dbName}" = "ALL PRIVILEGES"; 76 - }; 70 + name = "miniflux"; 71 + ensureDBOwnership = true; 77 72 } ]; 78 - ensureDatabases = [ dbName ]; 73 + ensureDatabases = [ "miniflux" ]; 79 74 }; 80 75 81 76 systemd.services.miniflux-dbsetup = { ··· 97 92 98 93 serviceConfig = { 99 94 ExecStart = "${cfg.package}/bin/miniflux"; 100 - User = dbUser; 95 + User = "miniflux"; 101 96 DynamicUser = true; 102 97 RuntimeDirectory = "miniflux"; 103 98 RuntimeDirectoryMode = "0700";
+10 -3
nixos/modules/services/web-apps/mobilizon.nix
··· 347 347 348 348 # Taken from here: 349 349 # https://framagit.org/framasoft/mobilizon/-/blob/1.1.0/priv/templates/setup_db.eex 350 + # TODO(to maintainers of mobilizon): the owner database alteration is necessary 351 + # as PostgreSQL 15 changed their behaviors w.r.t. to privileges. 352 + # See https://github.com/NixOS/nixpkgs/issues/216989 to get rid 353 + # of that workaround. 350 354 script = 351 355 '' 352 356 psql "${repoSettings.database}" -c "\ 353 357 CREATE EXTENSION IF NOT EXISTS postgis; \ 354 358 CREATE EXTENSION IF NOT EXISTS pg_trgm; \ 355 359 CREATE EXTENSION IF NOT EXISTS unaccent;" 360 + psql -tAc 'ALTER DATABASE "${repoSettings.database}" OWNER TO "${dbUser}";' 361 + 356 362 ''; 357 363 358 364 serviceConfig = { ··· 372 378 ensureUsers = [ 373 379 { 374 380 name = dbUser; 375 - ensurePermissions = { 376 - "DATABASE \"${repoSettings.database}\"" = "ALL PRIVILEGES"; 377 - }; 381 + # Given that `dbUser` is potentially arbitrarily custom, we will perform 382 + # manual fixups in mobilizon-postgres. 383 + # TODO(to maintainers of mobilizon): Feel free to simplify your setup by using `ensureDBOwnership`. 384 + ensureDBOwnership = false; 378 385 } 379 386 ]; 380 387 extraPlugins = with postgresql.pkgs; [ postgis ];
+2 -2
nixos/modules/services/web-apps/moodle.nix
··· 194 194 config = mkIf cfg.enable { 195 195 196 196 assertions = [ 197 - { assertion = cfg.database.createLocally -> cfg.database.user == user; 197 + { assertion = cfg.database.createLocally -> cfg.database.user == user && cfg.database.user == cfg.database.name; 198 198 message = "services.moodle.database.user must be set to ${user} if services.moodle.database.createLocally is set true"; 199 199 } 200 200 { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; ··· 220 220 ensureDatabases = [ cfg.database.name ]; 221 221 ensureUsers = [ 222 222 { name = cfg.database.user; 223 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 223 + ensureDBOwnership = true; 224 224 } 225 225 ]; 226 226 };
+1 -3
nixos/modules/services/web-apps/netbox.nix
··· 257 257 ensureUsers = [ 258 258 { 259 259 name = "netbox"; 260 - ensurePermissions = { 261 - "DATABASE netbox" = "ALL PRIVILEGES"; 262 - }; 260 + ensureDBOwnership = true; 263 261 } 264 262 ]; 265 263 };
+1 -1
nixos/modules/services/web-apps/nextcloud.nix
··· 1042 1042 ensureDatabases = [ cfg.config.dbname ]; 1043 1043 ensureUsers = [{ 1044 1044 name = cfg.config.dbuser; 1045 - ensurePermissions = { "DATABASE ${cfg.config.dbname}" = "ALL PRIVILEGES"; }; 1045 + ensureDBOwnership = true; 1046 1046 }]; 1047 1047 }; 1048 1048
+1 -1
nixos/modules/services/web-apps/onlyoffice.nix
··· 198 198 ensureDatabases = [ "onlyoffice" ]; 199 199 ensureUsers = [{ 200 200 name = "onlyoffice"; 201 - ensurePermissions = { "DATABASE \"onlyoffice\"" = "ALL PRIVILEGES"; }; 201 + ensureDBOwnership = true; 202 202 }]; 203 203 }; 204 204 };
+1 -1
nixos/modules/services/web-apps/outline.nix
··· 581 581 enable = true; 582 582 ensureUsers = [{ 583 583 name = "outline"; 584 - ensurePermissions."DATABASE outline" = "ALL PRIVILEGES"; 584 + ensureDBOwnership = true; 585 585 }]; 586 586 ensureDatabases = [ "outline" ]; 587 587 };
+1 -3
nixos/modules/services/web-apps/peering-manager.nix
··· 186 186 ensureUsers = [ 187 187 { 188 188 name = "peering-manager"; 189 - ensurePermissions = { 190 - "DATABASE \"peering-manager\"" = "ALL PRIVILEGES"; 191 - }; 189 + ensureDBOwnership = true; 192 190 } 193 191 ]; 194 192 };
-1
nixos/modules/services/web-apps/pixelfed.nix
··· 271 271 ensureDatabases = [ cfg.database.name ]; 272 272 ensureUsers = [{ 273 273 name = user; 274 - ensurePermissions = { }; 275 274 }]; 276 275 }; 277 276
+11 -2
nixos/modules/services/web-apps/tt-rss.nix
··· 529 529 assertion = cfg.database.password != null -> cfg.database.passwordFile == null; 530 530 message = "Cannot set both password and passwordFile"; 531 531 } 532 + { 533 + assertion = cfg.database.createLocally -> cfg.database.name == cfg.user && cfg.database.user == cfg.user; 534 + message = '' 535 + When creating a database via NixOS, the db user and db name must be equal! 536 + If you already have an existing DB+user and this assertion is new, you can safely set 537 + `services.tt-rss.database.createLocally` to `false` because removal of `ensureUsers` 538 + and `ensureDatabases` doesn't have any effect. 539 + ''; 540 + } 532 541 ]; 533 542 534 543 services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { ··· 632 641 enable = mkDefault true; 633 642 ensureDatabases = [ cfg.database.name ]; 634 643 ensureUsers = [ 635 - { name = cfg.user; 636 - ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; 644 + { name = cfg.database.user; 645 + ensureDBOwnership = true; 637 646 } 638 647 ]; 639 648 };
+1 -1
nixos/modules/services/web-servers/hydron.nix
··· 93 93 ensureDatabases = [ "hydron" ]; 94 94 ensureUsers = [ 95 95 { name = "hydron"; 96 - ensurePermissions = { "DATABASE hydron" = "ALL PRIVILEGES"; }; 96 + ensureDBOwnership = true; 97 97 } 98 98 ]; 99 99 };
+1 -1
nixos/tests/dex-oidc.nix
··· 49 49 ensureUsers = [ 50 50 { 51 51 name = "dex"; 52 - ensurePermissions = { "DATABASE dex" = "ALL PRIVILEGES"; }; 52 + ensureDBOwnership = true; 53 53 } 54 54 ]; 55 55 };
+1 -1
nixos/tests/ferretdb.nix
··· 39 39 ensureDatabases = [ "ferretdb" ]; 40 40 ensureUsers = [{ 41 41 name = "ferretdb"; 42 - ensurePermissions."DATABASE ferretdb" = "ALL PRIVILEGES"; 42 + ensureDBOwnership = true; 43 43 }]; 44 44 }; 45 45
+1 -3
nixos/tests/freshrss-pgsql.nix
··· 22 22 ensureUsers = [ 23 23 { 24 24 name = "freshrss"; 25 - ensurePermissions = { 26 - "DATABASE freshrss" = "ALL PRIVILEGES"; 27 - }; 25 + ensureDBOwnership = true; 28 26 } 29 27 ]; 30 28 initialScript = pkgs.writeText "postgresql-password" ''
+1 -1
nixos/tests/grafana/basic.nix
··· 55 55 ensureDatabases = [ "grafana" ]; 56 56 ensureUsers = [{ 57 57 name = "grafana"; 58 - ensurePermissions."DATABASE grafana" = "ALL PRIVILEGES"; 58 + ensureDBOwnership = true; 59 59 }]; 60 60 }; 61 61 systemd.services.grafana.after = [ "postgresql.service" ];
+1 -1
nixos/tests/hockeypuck.nix
··· 35 35 ensureDatabases = [ "hockeypuck" ]; 36 36 ensureUsers = [{ 37 37 name = "hockeypuck"; 38 - ensurePermissions."DATABASE hockeypuck" = "ALL PRIVILEGES"; 38 + ensureDBOwnership = true; 39 39 }]; 40 40 }; 41 41 };
+5 -7
nixos/tests/home-assistant.nix
··· 9 9 nodes.hass = { pkgs, ... }: { 10 10 services.postgresql = { 11 11 enable = true; 12 - 13 - # FIXME: hack for https://github.com/NixOS/nixpkgs/issues/216989 14 - # Should be replaced with ensureUsers again when a solution for that is found 15 - initialScript = pkgs.writeText "hass-setup-db.sql" '' 16 - CREATE ROLE hass WITH LOGIN; 17 - CREATE DATABASE hass WITH OWNER hass; 18 - ''; 12 + ensureDatabases = [ "hass" ]; 13 + ensureUsers = [{ 14 + name = "hass"; 15 + ensureDBOwnership = true; 16 + }]; 19 17 }; 20 18 21 19 services.home-assistant = {
+1 -2
nixos/tests/invidious.nix
··· 44 44 enable = true; 45 45 initialScript = pkgs.writeText "init-postgres-with-password" '' 46 46 CREATE USER kemal WITH PASSWORD 'correct horse battery staple'; 47 - CREATE DATABASE invidious; 48 - GRANT ALL PRIVILEGES ON DATABASE invidious TO kemal; 47 + CREATE DATABASE invidious OWNER kemal; 49 48 ''; 50 49 }; 51 50 };
+1 -1
nixos/tests/paperless.nix
··· 17 17 ensureDatabases = [ "paperless" ]; 18 18 ensureUsers = [ 19 19 { name = config.services.paperless.user; 20 - ensurePermissions = { "DATABASE \"paperless\"" = "ALL PRIVILEGES"; }; 20 + ensureDBOwnership = true; 21 21 } 22 22 ]; 23 23 };
-8
nixos/tests/pgadmin4.nix
··· 19 19 authentication = '' 20 20 host all all localhost trust 21 21 ''; 22 - ensureUsers = [ 23 - { 24 - name = "postgres"; 25 - ensurePermissions = { 26 - "DATABASE \"postgres\"" = "ALL PRIVILEGES"; 27 - }; 28 - } 29 - ]; 30 22 }; 31 23 32 24 services.pgadmin = {
+4 -6
nixos/tests/pgbouncer.nix
··· 17 17 18 18 systemd.services.postgresql = { 19 19 postStart = '' 20 - ${pkgs.postgresql}/bin/psql -U postgres -c "ALTER ROLE testuser WITH LOGIN PASSWORD 'testpass'"; 20 + ${pkgs.postgresql}/bin/psql -U postgres -c "ALTER ROLE testuser WITH LOGIN PASSWORD 'testpass'"; 21 + ${pkgs.postgresql}/bin/psql -U postgres -c "ALTER DATABASE testdb OWNER TO testuser;"; 21 22 ''; 22 23 }; 23 24 ··· 28 29 ensureUsers = [ 29 30 { 30 31 name = "testuser"; 31 - ensurePermissions = { 32 - "DATABASE testdb" = "ALL PRIVILEGES"; 33 - }; 34 32 }]; 35 33 authentication = '' 36 34 local testdb testuser scram-sha-256 ··· 40 38 pgbouncer = { 41 39 enable = true; 42 40 listenAddress = "localhost"; 43 - databases = { testdb = "host=/run/postgresql/ port=5432 auth_user=testuser dbname=testdb"; }; 41 + databases = { test = "host=/run/postgresql/ port=5432 auth_user=testuser dbname=testdb"; }; 44 42 authType = "scram-sha-256"; 45 43 authFile = testAuthFile; 46 44 }; ··· 55 53 56 54 # Test if we can make a query through PgBouncer 57 55 one.wait_until_succeeds( 58 - "psql 'postgres://testuser:testpass@localhost:6432/testdb' -c 'SELECT 1;'" 56 + "psql 'postgres://testuser:testpass@localhost:6432/test' -c 'SELECT 1;'" 59 57 ) 60 58 ''; 61 59 })
+1 -3
nixos/tests/powerdns-admin.nix
··· 87 87 ensureUsers = [ 88 88 { 89 89 name = "powerdnsadmin"; 90 - ensurePermissions = { 91 - "DATABASE powerdnsadmin" = "ALL PRIVILEGES"; 92 - }; 90 + ensureDBOwnership = true; 93 91 } 94 92 ]; 95 93 };
+1 -1
nixos/tests/sftpgo.nix
··· 156 156 ensureDatabases = [ "sftpgo" ]; 157 157 ensureUsers = [{ 158 158 name = "sftpgo"; 159 - ensurePermissions."DATABASE sftpgo" = "ALL PRIVILEGES"; 159 + ensureDBOwnership = true; 160 160 }]; 161 161 }; 162 162
+23
nixos/tests/tandoor-recipes.nix
··· 5 5 nodes.machine = { pkgs, ... }: { 6 6 services.tandoor-recipes = { 7 7 enable = true; 8 + extraConfig = { 9 + DB_ENGINE = "django.db.backends.postgresql"; 10 + POSTGRES_HOST = "/run/postgresql"; 11 + POSTGRES_USER = "tandoor_recipes"; 12 + POSTGRES_DB = "tandoor_recipes"; 13 + }; 14 + }; 15 + 16 + services.postgresql = { 17 + enable = true; 18 + ensureDatabases = [ "tandoor_recipes" ]; 19 + ensureUsers = [ 20 + { 21 + name = "tandoor_recipes"; 22 + ensureDBOwnership = true; 23 + } 24 + ]; 25 + }; 26 + 27 + systemd.services = { 28 + tandoor-recipes = { 29 + after = [ "postgresql.service" ]; 30 + }; 8 31 }; 9 32 }; 10 33
+1 -1
nixos/tests/vikunja.nix
··· 33 33 ensureDatabases = [ "vikunja-api" ]; 34 34 ensureUsers = [ 35 35 { name = "vikunja-api"; 36 - ensurePermissions = { "DATABASE \"vikunja-api\"" = "ALL PRIVILEGES"; }; 36 + ensureDBOwnership = true; 37 37 } 38 38 ]; 39 39 };
+3 -2
nixos/tests/wiki-js.nix
··· 10 10 enable = true; 11 11 settings.db.host = "/run/postgresql"; 12 12 settings.db.user = "wiki-js"; 13 + settings.db.db = "wiki-js"; 13 14 settings.logLevel = "debug"; 14 15 }; 15 16 services.postgresql = { 16 17 enable = true; 17 - ensureDatabases = [ "wiki" ]; 18 + ensureDatabases = [ "wiki-js" ]; 18 19 ensureUsers = [ 19 20 { name = "wiki-js"; 20 - ensurePermissions."DATABASE wiki" = "ALL PRIVILEGES"; 21 + ensureDBOwnership = true; 21 22 } 22 23 ]; 23 24 };