This article is about how to make backup of a database from filesystem in PostgreSQL. Also provides details on how to make and restore the database from filesystem. If you have come across case where you are required to start ‘psql’ database from filesystem backup. There might be case that some of Ubuntu files crashed during a blackout. The Ubuntu needs to be reinstalled. You do not have database backup files, you have somehow restored filesystem, or situation like, you forgot the AWS root password and you need to redo all setup right from database on other instance. This post is about second case, where I forgot the AWS root password, so I have attached the filesystem to other instance and trying to get the database up and running from mounted filesystem. There is way to recover the databases from the data folder only. So lets get going on How to Backup PostgreSQL Data From Files.

I am using AWS ec2 instance with focal.

Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal

Lets start on what are steps to recover PostgreSQL databases from raw physical files. To answer this in one line, just save or mount the the data directory to disk and When launching Postgres, set the parameter telling mounted data directory path.

This post assumes your PostgreSQL environment has following setup-

Contents

Steps – How to Backup PostgreSQL Data From Files

This section details out steps on how to backup PostgreSQL data from files.

Step 1 – Preparation for backup from raw files

Change ownership of data directory on mounted file system and provide required access. I have mounted data directory in ‘/mnt’ folder.

bhagwat@ip-172-31-14-170:~$ sudo chown -R postgres:postgres /mnt/var/lib/postgresql/10/main/
bhagwat@ip-172-31-14-170:~$ sudo chmod 700 /mnt/var/lib/postgresql/10/main/

Verify this change, since, It is important to take note of the ownership and permissions of the data directory because it is needed that new directory and old directory matches them.

bhagwat@ip-172-31-14-170:~$ sudo ls -la /mnt/var/lib/postgresql/10/main/
total 92
drwx------ 19 postgres postgres 4096 Jul 23 09:30 .
drwxr-xr-x 3 postgres postgres 4096 Jul 23 09:30 ..
-rw------- 1 postgres postgres 3 Jul 23 09:30 PG_VERSION
drwx------ 5 postgres postgres 4096 Jul 23 09:30 base
drwx------ 2 postgres postgres 4096 Jul 23 09:31 global
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_commit_ts
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_dynshmem
drwx------ 4 postgres postgres 4096 Jul 23 09:35 pg_logical
drwx------ 4 postgres postgres 4096 Jul 23 09:30 pg_multixact
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_notify
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_replslot
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_serial
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_snapshots
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_stat
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_stat_tmp
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_subtrans
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_tblspc
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_twophase
drwx------ 3 postgres postgres 4096 Jul 23 09:30 pg_wal
drwx------ 2 postgres postgres 4096 Jul 23 09:30 pg_xact
-rw------- 1 postgres postgres 88 Jul 23 09:30 postgresql.auto.conf
-rw------- 1 postgres postgres 130 Jul 23 09:30 postmaster.opts
-rw------- 1 postgres postgres 109 Jul 23 09:30 postmaster.pid

Stop PostgreSQL and verify its status

bhagwat@ip-172-31-14-170:~$ sudo systemctl stop postgresql
bhagwat@ip-172-31-14-170:~$ sudo systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Fri 2021-07-23 09:57:13 UTC; 12s ago
Main PID: 93086 (code=exited, status=0/SUCCESS)
Jul 23 03:49:07 ip-172-31-14-170 systemd[1]: Starting PostgreSQL RDBMS…
Jul 23 03:49:07 ip-172-31-14-170 systemd[1]: Finished PostgreSQL RDBMS.
Jul 23 09:57:13 ip-172-31-14-170 systemd[1]: postgresql.service: Succeeded.
Jul 23 09:57:13 ip-172-31-14-170 systemd[1]: Stopped PostgreSQL RDBMS.

Step 2- Changing Default Data Directory

Connect to your default psql database and verify the data directory.

postgresql data directory

This also shows the default database tables available after postgres installation.

Now change the data directory to mounted data directory. I have mounted data in ‘/mnt’ folder. With older postgresql versions you can also start with data_directory using “-D” option.

$ sudo vim /etc/postgresql/10/main/postgresql.conf
update data_directory in postgresql.conf

Step 3 – Start With New Data Directory

$ sudo service postgresql start
$ sudo service postgresql status
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
Active: active (exited) since Fri 2021-07-23 10:00:56 UTC; 4s ago
Process: 98844 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
Main PID: 98844 (code=exited, status=0/SUCCESS)
Jul 23 10:00:56 ip-172-31-14-170 systemd[1]: Starting PostgreSQL RDBMS…
Jul 23 10:00:56 ip-172-31-14-170 systemd[1]: Finished PostgreSQL RDBMS.

$ sudo -u postgres psql
psql (10.17 (Ubuntu 10.17-1.pgdg20.04+1))
Type "help" for help.
postgres=# \l
List of databases
Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges   
-----------+----------+----------+---------+---------+-----------------------
pgdb      | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =Tc/postgres         +
|          |          |         |         | postgres=CTc/postgres+
|          |          |         |         | pguser=CTc/postgres
postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 | 
template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
|          |          |         |         | postgres=CTc/postgres
template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
|          |          |         |         | postgres=CTc/postgres
vtpdb     | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =Tc/postgres         +
|          |          |         |         | postgres=CTc/postgres+
|          |          |         |         | pguser=CTc/postgres
vtpdb1    | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =Tc/postgres         +
|          |          |         |         | postgres=CTc/postgres+
|          |          |         |         | pguser=CTc/postgres
vtpdb2    | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =Tc/postgres         +
|          |          |         |         | postgres=CTc/postgres+
|          |          |         |         | pguser=CTc/postgres
(7 rows)
postgres=# \c vtpdb2
You are now connected to database "vtpdb2" as user "postgres".

This shows 4 more tables from mounted files system. We are interested in ‘vtpdb2’ database.

Step 4- Backup and Restore

Once the database and its related tables are available you can easily do backup of the database and restore to our default database.

Run pg_dump to back the database. Since you are logged in as different user, you need to mention user specifically, else you will have to do this with root access.

$pg_dump -h localhost -U pguser vtpdb2 > /home/bhagwat/vtpdb2_bkp.sql

Now run pg_restore. Do not forget to provide ‘localhost’ option.

$pg_restore -h localhost -U pguser -d vtpdb2 -1 /home/bhagwat/vtpdb2_bkp.sql 

Once this is done, you can revert back the changes in step 2, ie revert to your default data directory.

Troubleshooting –

I have faced few errors as follows

psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

For this I have tried to do the changes in pg_hba.conf. Also tried to do symlink with ‘tmp’ file, but it did not worked out.

ln -s /tmp/.s.PGSQL.5432 /var/run/postgresql/.s.PGSQL.5432

So, I had to purge the PostgreSQL and install it again to make it work.

$pg_restore -h localhost -U pguser -d vtpdb2 -1 /home/bhagwat/vtpdb2_bkp.sql 
pg_restore: [archiver (db)] Error while processing TOC:
pg_restore: [archiver (db)] Error from TOC entry 196, Table storage_elements pguser
pg_restore: [archiver (db)] Could not execute query: Error: role "pguser" does not exist
    Command was: ALTER Table storage_elements OWNER To pguser 

For this error, I have created ‘pguser’ in the default postgresql installation.

Next error was related to access permissions for ‘pguser’

$pg_restore -h localhost -U pguser -d vtpdb2 -1 /home/bhagwat/vtpdb2_bkp.sql 
pg_restore: [archiver (db)] Error while processing TOC: 
pg_restore: [archiver (db)] Error from TOC entry 5843, 0 0 Comment extension plpgsql 
pg_restore: [archiver (db)] Could not execute query: must be owner of extension plpgsql 
    Command was: COMMENT ON EXTENSION plpgsql IS 'PL/PgSQL procedural language';

For this error to solve make ‘pguser’ as superuser in PostgreSQL.

I hope you have enjoyed this post on How to Backup PostgreSQL Data From Files.