Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/postgresql: document psql 15 changes #267238

Merged
merged 7 commits into from
Nov 17, 2023
71 changes: 71 additions & 0 deletions nixos/modules/services/databases/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,77 @@ By default, PostgreSQL stores its databases in {file}`/var/lib/postgresql/$psqlS
services.postgresql.dataDir = "/data/postgresql";
```

## Initializing {#module-services-postgres-initializing}

As of NixOS 23.11, `services.postgresql.ensureUsers.*.ensurePermissions` has been deprecated, after a change to default permissions in PostgreSQL 15 invalidated most of its previous use cases:

- In psql < 15, `ALL PRIVILEGES` used to include `CREATE TABLE`, where in psql >= 15 that would be a separate permission
- psql >= 15 instead gives only the database owner create permissions
- Even on psql < 15 (or databases migrated to >= 15), it is recommended to manually assign permissions along these lines
- https://www.postgresql.org/docs/release/15.0/
- https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PRIV

### Assigning ownership {#module-services-postgres-initializing-ownership}

The corresponding system user should be database owner in most cases. This can be done with `services.postgresql.ensureUsers.*.ensureDBOwnership = true;`
bendlas marked this conversation as resolved.
Show resolved Hide resolved

### Assigning extra permissions {#module-services-postgres-initializing-extra-permissions}

For many cases, it will be enough to have the database user be the
owner. Until `services.postgresql.ensureUsers.*.ensurePermissions` has
been re-thought, if more users need access to the database, please use
one of the following approaches:

**WARNING:** `services.postgresql.initialScript` is not recommended for `ensurePermissions` replacement as …
for this, as that is *only run on first start of PostgreSQL*.

#### Assigning permissions in database `postStart` {#module-services-postgres-initializing-extra-permissions-post-start}

```nix
systemd.services.postgresql.postStart = lib.mkAfter ''
$PSQL service1 -c 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "extraUser1"'
$PSQL service1 -c 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "extraUser1"'
# ....
'';
```

**Advantage:** compatible with postgres < 15, because it's run
as the database superuser `postgres`.

**Disadvantage:** need to take care of ordering yourself. In this
example, `mkAfter` ensures that permissions are assigned after any
databases from `ensureDatabases` and `extraUser1` from `ensureUsers`
are already created.

#### Assigning permissions in service `preStart` or intermediate oneshot service {#module-services-postgres-initializing-extra-permissions-service-pre-start}

```nix
systemd.services."service1".preStart = ''
$PSQL -c 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "extraUser1"'
$PSQL -c 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "extraUser1"'
bendlas marked this conversation as resolved.
Show resolved Hide resolved
# ....
'';
```

```nix
systemd.services."migrate-service1-db1" = {
type = "oneshot";
requiredBy = "service1.service";
before = "service1.service";
after = "postgresql.service";
serviceConfig.User = "service1";
bendlas marked this conversation as resolved.
Show resolved Hide resolved
script = ''
$PSQL -c 'GRANT SELECT ON ALL TABLES IN SCHEMA public TO "extraUser1"'
$PSQL -c 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO "extraUser1"'
# ....
'';
};
```

**Advantage:** re-uses systemd's dependency ordering

**Disadvantage:** relies on service user having grant permission. To be combined with `ensureDBOwnership`.

## Upgrading {#module-services-postgres-upgrading}

::: {.note}
Expand Down