Recently, I upgraded a server running Ubuntu 22.04 to 24.04, that also comes with PostgreSQL 16. For some odd reasons, the Postgres server was not managed by Ansible, and changes previously made to Postgres 15 was not recorded.

I noticed that the backup database (pg_dump) was not working properly, the backup database size was just a few kilobytes. Let’s investigate, shall we?

root@toto:/etc/cron.daily# ./postgresql-backup
pg_dump: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  Peer authentication failed for user "postgres"

You might be wondering, what’s in postgresql-backup? Well, nothing fancy.

root@toto:/etc/cron.daily# head postgresql-backup
#!/bin/bash
# 2014-06-06
# NOT YET Ansible managed

MAILTO=root
BACKUP_DIR=/srv/backup/database/postgresql

/usr/bin/pg_dump -U postgres -Fc awesomedb  | /bin/gzip > ${BACKUP_DIR}/awesomedb.pgdump_`date +'%Y-%m-%d'`.gz

So, the error message is similar to an issue with Postgres I had a long time ago.

This has something to do the authentication configured in the pg_hba.conf which use peer method. The peer authentication method works by obtaining the client’s operating system user name from the kernel and using it as the allowed database user name (with optional user name mapping) based on [1].

Let’s check what’s configured in pg_hba.conf file.

root@toto:/etc/cron.daily# cat /etc/postgresql/16/main/pg_hba.conf  | grep peer
# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert".
local   all             postgres                                peer
local   all             all                                     peer
local   replication     all                                     peer

In my backup script, the pg_dump was run as a root user, and it would have worked if had it was run by the operating system postgres user (I did test that). There are a few solutions to this issue according to the internet, however, I’m going to make use the “user name maps” feature [2], to map the system root user to the postgres database user.

The user name maps are defined in the ident map file named pg_ident.conf, it has the following format:

map-name system-username database-username

Currently there is no maps defined in the pg_ident.conf. We can see this by checking the last 2 line in the file.

root@toto:/etc/systemd# tail -2 /etc/postgresql/16/main/pg_ident.conf

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME

In my case, I want to append 2 lines to the end of the /etc/postgresql/16/main/pg_ident.conf to map root and postgres system users to the postgres database user and call it totomap.

root@toto:~# cat << EOF | tee -a /etc/postgresql/16/main/pg_ident.conf
> totomap         postgres                postgres
> totomap         root                    postgres
> EOF
totomap         postgres                postgres
totomap         root                    postgres

root@toto:~# tail -2 /etc/postgresql/16/main/pg_ident.conf
totomap         postgres                postgres
totomap         root                    postgres

Next step is to add the map=totomap to the postgres user in pg_hba.conf. I’m going to use sed command do this, but if you follow along, you can edit the pg_hba.conf file manually with vim or nano.

root@toto:~# grep postgres /etc/postgresql/16/main/pg_hba.conf
local   all             postgres                                peer

root@toto:~# sed -i 's/\(^local.*all.*postgres.*peer$\)/\1    map=totomap/' /etc/postgresql/16/main/pg_hba.conf

root@toto:~# grep postgres /etc/postgresql/16/main/pg_hba.conf
local   all             postgres                                peer    map=totomap

We’re almost done. Just need to restart the postgres service and try re-run the backup script (pg_dump).

root@toto:~# systemctl restart postgresql
root@toto:~# /etc/cron.daily/postgresql-backup
root@toto:~# echo $?
0

It’s working. Please note, I’m not a database admin, my interaction with PostsgreSQL is very limited. The method used in this post might not be a good practice, but works well enough for my use case.

BONUS:

Normally, when we want to connect to the Postgres server without authentication, we will switch to the postgres (system) user first (as it has a database match this name and allow access with peer authentication method.)

For example, this is what we can do:

root@toto:~# su - postgres
postgres@toto:~$ psql
psql (16.3 (Ubuntu 16.3-0ubuntu0.24.04.1))
Type "help" for help.

postgres=#

If we tried to run psql command from the root user, we would get an error:

root@toto:~# psql
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "root" does not exist

However, after adding a new user map (totomap in this example), we can connect to the Postgres server from root (system) user directly. Here’s how:

root@toto:~# psql -U postgres
psql (16.3 (Ubuntu 16.3-0ubuntu0.24.04.1))
Type "help" for help.

postgres=#

References: