diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index 2c9b0242e9e8..7abcc36257f5 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -1286,6 +1286,12 @@ "module-services-postgres-initializing-extra-permissions-service-user-oneshot": [ "index.html#module-services-postgres-initializing-extra-permissions-service-user-oneshot" ], + "module-services-postgres-authentication": [ + "index.html#module-services-postgres-authentication" + ], + "module-services-postgres-authentication-user-mapping": [ + "index.html#module-services-postgres-authentication-user-mapping" + ], "module-services-postgres-upgrading": [ "index.html#module-services-postgres-upgrading" ], diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix index d83db34b9aa3..df586356306a 100644 --- a/nixos/modules/services/continuous-integration/hydra/default.nix +++ b/nixos/modules/services/continuous-integration/hydra/default.nix @@ -564,16 +564,14 @@ in services.postgresql.enable = lib.mkIf haveLocalDB true; services.postgresql.identMap = lib.optionalString haveLocalDB '' - hydra-users hydra hydra - hydra-users hydra-queue-runner hydra - hydra-users hydra-www hydra - hydra-users root hydra - # The postgres user is used to create the pg_trgm extension for the hydra database - hydra-users postgres postgres + hydra hydra hydra + hydra hydra-queue-runner hydra + hydra hydra-www hydra + hydra root hydra ''; services.postgresql.authentication = lib.optionalString haveLocalDB '' - local hydra all ident map=hydra-users + local all hydra peer map=hydra ''; }; diff --git a/nixos/modules/services/databases/postgresql.md b/nixos/modules/services/databases/postgresql.md index daff317e9e2b..e1256c9672f2 100644 --- a/nixos/modules/services/databases/postgresql.md +++ b/nixos/modules/services/databases/postgresql.md @@ -170,6 +170,38 @@ are already created. } ``` +## Authentication {#module-services-postgres-authentication} + +Local connections are made through unix sockets by default and support [peer authentication](https://www.postgresql.org/docs/current/auth-peer.html). +This allows system users to login with database roles of the same name. +For example, the `postgres` system user is allowed to login with the database role `postgres`. + +System users and database roles might not always match. +In this case, to allow access for a service, you can create a [user name map](https://www.postgresql.org/docs/current/auth-username-maps.html) between system roles and an existing database role. + +### User Mapping {#module-services-postgres-authentication-user-mapping} + +Assume that your app creates a role `admin` and you want the `root` user to be able to login with it. +You can then use [](#opt-services.postgresql.identMap) to define the map and [](#opt-services.postgresql.authentication) to enable it: + +```nix +services.postgresql = { + identMap = '' + admin root admin + ''; + authentication = '' + local all admin peer map=admin + ''; +} +``` + +::: {.warning} +To avoid conflicts with other modules, you should never apply a map to `all` roles. +Because PostgreSQL will stop on the first matching line in `pg_hba.conf`, a line matching all roles would lock out other services. +Each module should only manage user maps for the database roles that belong to this module. +Best practice is to name the map after the database role it manages to avoid name conflicts. +::: + ## Upgrading {#module-services-postgres-upgrading} ::: {.note} diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index abcb704b887a..48ff4c2a48ef 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -274,6 +274,14 @@ in Defines the mapping from system users to database users. See the [auth doc](https://postgresql.org/docs/current/auth-username-maps.html). + + There is a default map "postgres" which is used for local peer authentication + as the postgres superuser role. + For example, to allow the root user to login as the postgres superuser, add: + + ``` + postgres root postgres + ``` ''; }; @@ -674,12 +682,20 @@ in (mkBefore "# Generated file; do not edit!") (mkAfter '' # default value of services.postgresql.authentication + local all postgres peer map=postgres local all all peer host all all 127.0.0.1/32 md5 host all all ::1/128 md5 '') ]; + # The default allows to login with the same database username as the current system user. + # This is the default for peer authentication without a map, but needs to be made explicit + # once a map is used. + services.postgresql.identMap = mkAfter '' + postgres postgres postgres + ''; + services.postgresql.systemCallFilter = mkMerge [ (mapAttrs (const mkDefault) { "@system-service" = true; diff --git a/nixos/tests/postgresql/postgresql.nix b/nixos/tests/postgresql/postgresql.nix index a88143c6421a..ecf1b5552804 100644 --- a/nixos/tests/postgresql/postgresql.nix +++ b/nixos/tests/postgresql/postgresql.nix @@ -54,6 +54,9 @@ let services.postgresql = { inherit package; enable = true; + identMap = '' + postgres root postgres + ''; # TODO(@Ma27) split this off into its own VM test and move a few other # extension tests to use postgresqlTestExtension. extensions = ps: with ps; [ plv8 ]; @@ -73,7 +76,7 @@ let in '' def check_count(statement, lines): - return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format( + return 'test $(psql -U postgres postgres -tAc "{}"|wc -l) -eq {}'.format( statement, lines )