Identity Mapping in PostgreSQL (pg_ident.conf)
Table of Contents
1. What is pg_ident.conf?
pg_ident.conf defines user name maps — rules that translate externally authenticated identities (OS logins, certificate CNs, Kerberos principals, etc.) into PostgreSQL roles. By default, no mapping is configured, use pg_ident.conf when the external identity should not match the PostgreSQL role name exactly (e.g., mapping OS user rajesh to database role app_readonly).
- When to use: Peer, ident, gss, sspi, cert, and radius authentication methods.
- When NOT to use: Password-based methods (md5, scram-sha-256) ignore this file entirely.
- Key point: A map has no effect until referenced by name from
pg_hba.confusingmap=MAPNAME.
Where are the files? Check with:
postgres=# SHOW hba_file; hba_file ---------------------------------- /pgData/pgsql17/data/pg_hba.conf (1 row) postgres=# SHOW ident_file; ident_file ------------------------------------ /pgData/pgsql17/data/pg_ident.conf (1 row) postgres=#
2. File Format & Configuration
pg_ident.conf has three whitespace-separated columns per line: ()
# MAPNAME SYSTEM-USERNAME PG-USERNAME Label (any name) OS USERNAME PostgreSQL (user or role)
- MAPNAME: A label you choose, referenced later in
pg_hba.conf. - SYSTEM-USERNAME: The external identity (OS username, certificate CN, etc.).
- PG-USERNAME: The PostgreSQL role to map to.
- Entries are evaluated top-to-bottom, first match wins.
Reference the map in pg_hba.conf: (Example)
# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all all peer map=demo_map
hostssl all all 0.0.0.0/0 cert map=demo_mapReload configuration without restart:
SELECT pg_reload_conf(); <---- from psql
# OR
pg_ctl reload -D $PGDATA <---- As postgres os user # OR systemctl reload postgresql <---- As root os user3. Simple 1:1 Mapping
Map an OS user to a PostgreSQL role with a one-to-one relationship:
# MAPNAME SYSTEM-USERNAME PG-USERNAME demo_map rajesh rajesh
4. Simple Mapping (Many-to-One)
Many-to-one mapping: Multiple identities map to the same role (useful for shared service accounts)
# MAPNAME SYSTEM-USERNAME PG-USERNAME
demo_map amit app_readonly
demo_map priya app_readonly
demo_map sandeep app_readonly
demo_map anjali app_readonlyCombined with log_connections = on, you retain an audit trail of which identity initiated each connection.
5. Certificate-Based Mapping
pg_ident.conf works with client certificate authentication by matching against the certificate’s Common Name (CN) instead of OS username:
# pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all 0.0.0.0/0 cert clientcert=verify-full map=demo_map
# pg_ident.conf
# MAPNAME SYSTEM-USERNAME PG-USERNAME
demo_map app-client-01 app_service6. Complete Workflow: Setup, Configure & Test
-- 1. Create the OS user
[root@pgdb02 ~]# useradd rajesh
[root@pgdb02 ~]# id rajesh
uid=1003(rajesh) gid=1003(rajesh) groups=1003(rajesh)
[root@pgdb02 ~]#
[root@pgdb02 ~]# useradd ravi
[root@pgdb02 ~]# id ravi
uid=1004(ravi) gid=1004(ravi) groups=1004(ravi)
[root@pgdb02 ~]#
-- 2. Create the PostgreSQL role
postgres=# CREATE USER rajesh;
CREATE ROLE
postgres=#
postgres=# CREATE USER ravi;
CREATE ROLE
postgres=#
*** mapped user rajesh only, user ravi not mapped on pg_ident.conf. Please note this.
-- 3. Add mapping to pg_ident.conf
# MAPNAME SYSTEM-USERNAME PG-USERNAME
demo_map rajesh rajesh
-- 4. Add rule to pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all all peer map=demo_map
-- 5. Reload configuration
[postgres@pgdb02 ~]$ pg_ctl reload -D /pgData/pgsql17/data/
server signaled
[postgres@pgdb02 ~]$
-- 6. Test successful connection
[root@pgdb02 ~]# su - rajesh
[rajesh@pgdb02 ~]$ id
uid=1003(rajesh) gid=1003(rajesh) groups=1003(rajesh)
[rajesh@pgdb02 ~]$
[rajesh@pgdb02 ~]$ psql -d postgres
psql (17.10)
Type "help" for help.
postgres=> \c
You are now connected to database "postgres" as user "rajesh".
postgres=>
postgres=> SELECT current_user, session_user;
current_user | session_user
--------------+--------------
rajesh | rajesh
(1 row)
postgres=>
2026-07-08 15:11:59.936 +08 [4662] LOG: connection received: host=[local]
2026-07-08 15:11:59.939 +08 [4662] LOG: connection authenticated: identity="rajesh" method=peer (/pgData/pgsql17/data/pg_hba.conf:132)
2026-07-08 15:11:59.939 +08 [4662] LOG: connection authorized: user=rajesh database=postgres application_name=psql
-- 7. Test failure case (unmapped user - ravi)
[root@pgdb02 ~]# su - ravi
[ravi@pgdb02 ~]$ id
uid=1004(ravi) gid=1004(ravi) groups=1004(ravi)
[ravi@pgdb02 ~]$
[ravi@pgdb02 ~]$ psql -d postgres
psql: error: connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "ravi"
[ravi@pgdb02 ~]$
2026-07-08 15:12:43.890 +08 [4704] LOG: connection received: host=[local]
2026-07-08 15:12:43.893 +08 [4704] LOG: connection authenticated: identity="ravi" method=peer (/pgData/pgsql17/data/pg_hba.conf:132)
2026-07-08 15:12:43.893 +08 [4704] LOG: no match in usermap "demo_map" for user "ravi" authenticated as "ravi"
2026-07-08 15:12:43.894 +08 [4704] FATAL: Peer authentication failed for user "ravi"
2026-07-08 15:12:43.894 +08 [4704] DETAIL: Connection matched file "/pgData/pgsql17/data/pg_hba.conf" line 132: " local all all peer map=demo_map"