PostgreSQL : pg_basebackup and restore

Published: May 22, 2023 by Isaac Johnson

I’ve had a few primary node crashes lately, some of my own doing. One was due to me just knocking the power cord out and the battery draining. Regardless of cause, it made me realize the danger of having a production database without any backups.

Today we’ll use pg_basebackup to create a full backup of a PosgreSQL cluster and restore it elsewhere (to illustrate the process).

Postgres Backups

First, let’s review the cluster in question

isaac@isaac-MacBookAir:~$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

We have a standard PostgreSQL 12 DB hosted on the default port of 5432.

Next, we’ll login and create a super user I can use later if needed

isaac@isaac-MacBookAir:~$ sudo su - postgres
[sudo] password for isaac:
postgres@isaac-MacBookAir:~$ psql
psql (12.14 (Ubuntu 12.14-0ubuntu0.20.04.1))
Type "help" for help.

postgres=# CREATE USER builder WITH SUPERUSER;
CREATE ROLE
postgres=# ALTER USER builder WITH PASSWORD 'NotTheRealPassword';
ALTER ROLE
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO builder;
ALTER DEFAULT PRIVILEGES
postgres=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO builder;
ALTER DEFAULT PRIVILEGES
postgres=# \q

NAS mounts

At this moment, I have a NAS mount for the NFS provisioner on the host

postgres@isaac-MacBookAir:~$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda2 during installation
UUID=71e567ec-f9d6-48df-813e-ebb14d2ae929 /               ext4    errors=remount-ro 0       1
# /boot/efi was on /dev/sda1 during installation
UUID=9171-667C  /boot/efi       vfat    umask=0077      0       1
/swapfile                                 none            swap    sw              0       0
192.168.1.129:/volume1/k3snfs   /mnt/nfs/k3snfs nfs     auto,nofail,noatime,nolock,intr,tcp,actimeo=1800        0       0

But to be thorough, let us create a new backup mount just for databases.

I’ll create a new folder in Synology

/content/images/2023/05/pgbackup-01.png

If this volume had PHI and/or PII, as is sometimes the case in my profession, I would encrypt it. As it stands, this has only metrics data and some container images

/content/images/2023/05/pgbackup-02.png

I’ll change user perms as necessary

/content/images/2023/05/pgbackup-03.png

Next, I’ll right-click and edit

/content/images/2023/05/pgbackup-04.png

Then on “NFS Permissions”, I’ll whitelist this primary node IP. In fact, just to cover IP movement, I’ll whitelist the CIDR of the node pools and map all users to admin.

/content/images/2023/05/pgbackup-05.png

Once saved, I can see the NFS rule

/content/images/2023/05/pgbackup-06.png

Mounting backup dir with NFS

Now to use it, back on the primary node, I’ll create a mount point

$ sudo mkdir /mnt/psqlbackups
[sudo] password for isaac:

Then edit fstab and fire up the mount

isaac@isaac-MacBookAir:~$ sudo vi /etc/fstab
isaac@isaac-MacBookAir:~$ cat /etc/fstab | tail -n2
192.168.1.129:/volume1/k3snfs   /mnt/nfs/k3snfs nfs     auto,nofail,noatime,nolock,intr,tcp,actimeo=1800        0       0
192.168.1.129:/volume1/postgres-prod-dbbackups  /mnt/psqlbackups nfs    auto,nofail,noatime,nolock,intr,tcp,actimeo=1800        0       0

isaac@isaac-MacBookAir:~$ sudo mount -a

I can test by creating a file and seeing that it lands in the NAS

/content/images/2023/05/pgbackup-07.png

Now I can launch the pg_basebackup command using -Ft for tar format and -z for gzip compression.

isaac@isaac-MacBookAir:~$ pg_basebackup -h localhost -p 5432 -U builder -D /mnt/psqlbackups/2023-05-21 -Ft -z -Xs -P -v
Password:
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 3/5D000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_174464"
502741/502741 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 3/5D0D3178
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed

Lastly, I can see the full database there on external storage

isaac@isaac-MacBookAir:~$ ls -ltrah /mnt/psqlbackups/2023-05-21
total 107M
drwxrwxrwx 5 root root  4.0K May 21 06:49 ..
drwxrwxrwx 2 1024 users 4.0K May 21 06:52 .
-rwxrwxrwx 1 1024 users 107M May 21 06:53 base.tar.gz
-rwxrwxrwx 1 1024 users 346K May 21 06:53 pg_wal.tar.gz

Restoring

I’ll setup a new server

builder@builder-T100:~$ sudo apt update && sudo apt -y install vim bash-completion wget
[sudo] password for builder:
Sorry, try again.
[sudo] password for builder:
Hit:1 http://us.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 https://download.docker.com/linux/ubuntu focal InRelease
Get:3 http://us.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://us.archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:6 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 DEP-11 Metadata [275 kB]
Get:7 http://us.archive.ubuntu.com/ubuntu focal-updates/universe amd64 DEP-11 Metadata [409 kB]
Get:8 http://us.archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 DEP-11 Metadata [940 B]
Get:9 http://us.archive.ubuntu.com/ubuntu focal-backports/main amd64 DEP-11 Metadata [7,976 B]
Get:10 http://us.archive.ubuntu.com/ubuntu focal-backports/universe amd64 DEP-11 Metadata [30.5 kB]
Get:11 http://security.ubuntu.com/ubuntu focal-security/main amd64 DEP-11 Metadata [59.8 kB]
Get:12 http://security.ubuntu.com/ubuntu focal-security/universe amd64 DEP-11 Metadata [95.6 kB]
Get:13 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 DEP-11 Metadata [940 B]
Fetched 1,216 kB in 1s (1,026 kB/s)
Error: Timeout was reached
Reading package lists... Done
Building dependency tree
Reading state information... Done
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree
Reading state information... Done
bash-completion is already the newest version (1:2.10-1ubuntu1).
bash-completion set to manually installed.
vim is already the newest version (2:8.1.2269-1ubuntu5.14).
wget is already the newest version (1.20.3-1ubuntu2).
wget set to manually installed.
The following packages were automatically installed and are no longer required:
  gir1.2-goa-1.0 libfprint-2-tod1 libfwupdplugin1 libllvm10 libxmlb1
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.

Get Postgres apt repo and keys

builder@builder-T100:~$ curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc|sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
builder@builder-T100:~$ echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |sudo tee  /etc/apt/sources.list.d/pgdg.list
deb http://apt.postgresql.org/pub/repos/apt/ focal-pgdg main

Now we can install PostgreSQL 12

builder@builder-T100:~$ sudo apt update && sudo apt -y install vim bash-completion wget
[sudo] password for builder:
Sorry, try again.
[sudo] password for builder:
Hit:1 http://us.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 https://download.docker.com/linux/ubuntu focal InRelease
Get:3 http://us.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://us.archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:6 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 DEP-11 Metadata [275 kB]
Get:7 http://us.archive.ubuntu.com/ubuntu focal-updates/universe amd64 DEP-11 Metadata [409 kB]
Get:8 http://us.archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 DEP-11 Metadata [940 B]
Get:9 http://us.archive.ubuntu.com/ubuntu focal-backports/main amd64 DEP-11 Metadata [7,976 B]
Get:10 http://us.archive.ubuntu.com/ubuntu focal-backports/universe amd64 DEP-11 Metadata [30.5 kB]
Get:11 http://security.ubuntu.com/ubuntu focal-security/main amd64 DEP-11 Metadata [59.8 kB]
Get:12 http://security.ubuntu.com/ubuntu focal-security/universe amd64 DEP-11 Metadata [95.6 kB]
Get:13 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 DEP-11 Metadata [940 B]
Fetched 1,216 kB in 1s (1,026 kB/s)
Error: Timeout was reached
Reading package lists... Done
Building dependency tree
....

We can now install PG 12

builder@builder-T100:~$ sudo apt update && sudo apt -y install postgresql-12 postgresql-client-12
[sudo] password for builder:
Hit:1 http://us.archive.ubuntu.com/ubuntu focal InRelease
Get:2 http://us.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Hit:3 https://download.docker.com/linux/ubuntu focal InRelease
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://us.archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:6 http://us.archive.ubuntu.com/ubuntu focal-updates/main i386 Packages [822 kB]
Get:7 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [2,567 kB]
Get:8 http://security.ubuntu.com/ubuntu focal-security/main amd64 DEP-11 Metadata [59.8 kB]
Hit:9 http://apt.postgresql.org/pub/repos/apt focal-pgdg InRelease
Get:10 http://us.archive.ubuntu.com/ubuntu focal-updates/main Translation-en [433 kB]
Get:11 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 DEP-11 Metadata [274 kB]
Get:12 http://us.archive.ubuntu.com/ubuntu focal-updates/restricted amd64 Packages [1,879 kB]
Get:13 http://us.archive.ubuntu.com/ubuntu focal-updates/restricted Translation-en [264 kB]
Get:14 http://us.archive.ubuntu.com/ubuntu focal-updates/universe amd64 DEP-11 Metadata [410 kB]
Get:15 http://us.archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 DEP-11 Metadata [940 B]
Get:16 http://security.ubuntu.com/ubuntu focal-security/universe amd64 DEP-11 Metadata [95.5 kB]
Get:17 http://us.archive.ubuntu.com/ubuntu focal-backports/main amd64 DEP-11 Metadata [8,000 B]
Get:18 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 DEP-11 Metadata [940 B]
Get:19 http://us.archive.ubuntu.com/ubuntu focal-backports/universe amd64 DEP-11 Metadata [30.5 kB]

We can double check it is enabled to come up after reboot

builder@builder-T100:~$ systemctl is-enabled postgresql
enabled

And that it’s running (or at least loaded)

builder@builder-T100:~$ sudo systemctl status postgresql.service
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2023-05-21 19:11:02 CDT; 10h ago
   Main PID: 2654149 (code=exited, status=0/SUCCESS)
      Tasks: 0 (limit: 9099)
     Memory: 0B
     CGroup: /system.slice/postgresql.service

May 21 19:11:02 builder-T100 systemd[1]: Starting PostgreSQL RDBMS...
May 21 19:11:02 builder-T100 systemd[1]: Finished PostgreSQL RDBMS.

This new host never had NFS mounts, so we’ll need to add nfs-common

builder@builder-T100:~$ sudo apt-get install nfs-common
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  gir1.2-goa-1.0 libfprint-2-tod1 libfwupdplugin1 libxmlb1
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  keyutils libnfsidmap2 libtirpc-common libtirpc3 rpcbind
Suggested packages:
  open-iscsi watchdog
The following NEW packages will be installed:
  keyutils libnfsidmap2 libtirpc-common libtirpc3 nfs-common rpcbind
0 upgraded, 6 newly installed, 0 to remove and 8 not upgraded.
Need to get 405 kB of archives.
After this operation, 1,519 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 libtirpc-common all 1.2.5-1ubuntu0.1 [7,712 B]
Get:2 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 libtirpc3 amd64 1.2.5-1ubuntu0.1 [77.9 kB]
Get:3 http://us.archive.ubuntu.com/ubuntu focal/main amd64 rpcbind amd64 1.2.5-8 [42.8 kB]
Get:4 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 keyutils amd64 1.6-6ubuntu1.1 [44.8 kB]
Get:5 http://us.archive.ubuntu.com/ubuntu focal/main amd64 libnfsidmap2 amd64 0.25-5.1ubuntu1 [27.9 kB]
Get:6 http://us.archive.ubuntu.com/ubuntu focal-updates/main amd64 nfs-common amd64 1:1.3.4-2.5ubuntu3.4 [204 kB]
Fetched 405 kB in 0s (1,078 kB/s)
Selecting previously unselected package libtirpc-common.
(Reading database ... 188138 files and directories currently installed.)
Preparing to unpack .../0-libtirpc-common_1.2.5-1ubuntu0.1_all.deb ...
Unpacking libtirpc-common (1.2.5-1ubuntu0.1) ...
Selecting previously unselected package libtirpc3:amd64.
Preparing to unpack .../1-libtirpc3_1.2.5-1ubuntu0.1_amd64.deb ...
Unpacking libtirpc3:amd64 (1.2.5-1ubuntu0.1) ...
Selecting previously unselected package rpcbind.
Preparing to unpack .../2-rpcbind_1.2.5-8_amd64.deb ...
Unpacking rpcbind (1.2.5-8) ...
Selecting previously unselected package keyutils.
Preparing to unpack .../3-keyutils_1.6-6ubuntu1.1_amd64.deb ...
Unpacking keyutils (1.6-6ubuntu1.1) ...
Selecting previously unselected package libnfsidmap2:amd64.
Preparing to unpack .../4-libnfsidmap2_0.25-5.1ubuntu1_amd64.deb ...
Unpacking libnfsidmap2:amd64 (0.25-5.1ubuntu1) ...
Selecting previously unselected package nfs-common.
Preparing to unpack .../5-nfs-common_1%3a1.3.4-2.5ubuntu3.4_amd64.deb ...
Unpacking nfs-common (1:1.3.4-2.5ubuntu3.4) ...
Setting up libtirpc-common (1.2.5-1ubuntu0.1) ...
Setting up keyutils (1.6-6ubuntu1.1) ...
Setting up libnfsidmap2:amd64 (0.25-5.1ubuntu1) ...
Setting up libtirpc3:amd64 (1.2.5-1ubuntu0.1) ...
Setting up rpcbind (1.2.5-8) ...
Created symlink /etc/systemd/system/multi-user.target.wants/rpcbind.service → /lib/systemd/system/rpcbind.service.
Created symlink /etc/systemd/system/sockets.target.wants/rpcbind.socket → /lib/systemd/system/rpcbind.socket.
Setting up nfs-common (1:1.3.4-2.5ubuntu3.4) ...

Creating config file /etc/idmapd.conf with new version
Adding system user `statd' (UID 130) ...
Adding new user `statd' (UID 130) with group `nogroup' ...
Not creating home directory `/var/lib/nfs'.
Created symlink /etc/systemd/system/multi-user.target.wants/nfs-client.target → /lib/systemd/system/nfs-client.target.
Created symlink /etc/systemd/system/remote-fs.target.wants/nfs-client.target → /lib/systemd/system/nfs-client.target.
nfs-utils.service is a disabled or a static unit, not starting it.
Processing triggers for systemd (245.4-4ubuntu3.21) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.9) ...
Error: Timeout was reached

I’ll create a mount and add a line to /etc/fstab

builder@builder-T100:~$ sudo mkdir /mnt/psqlbackups

builder@builder-T100:~$ cat /etc/fstab | tail -n2
/swapfile                                 none            swap    sw              0       0
192.168.1.129:/volume1/postgres-prod-dbbackups  /mnt/psqlbackups nfs    auto,nofail,noatime,nolock,intr,tcp,actimeo=1800        0       0

At this point, between nfs-common, psql and other updates, I decided just to reboot

builder@builder-T100:~$ sudo reboot
Connection to 192.168.1.99 closed by remote host.
Connection to 192.168.1.99 closed.

Once back in, I’ll stop postgres and verify the data directory

builder@builder-T100:~$ sudo systemctl stop postgresql.service
[sudo] password for builder:
builder@builder-T100:~$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 down   postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

builder@builder-T100:~$ sudo su -
root@builder-T100:~# ls /var/lib/postgresql/12/main/
base    pg_commit_ts  pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf
global  pg_dynshmem   pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postmaster.opts

Next I’ll check I can see the contents of the backup

root@builder-T100:~# tar tfv /mnt/psqlbackups/2023-05-21/base.tar.gz
-rw------- postgres/postgres 226 2023-05-21 06:52 backup_label
-rw------- postgres/postgres   0 2023-05-21 06:52 tablespace_map
drwx------ postgres/postgres   0 2022-10-31 06:27 pg_replslot/
drwx------ postgres/postgres   0 2022-10-31 06:27 pg_twophase/
drwx------ postgres/postgres   0 2022-10-31 06:27 pg_dynshmem/
drwx------ postgres/postgres   0 2023-05-13 09:45 pg_xact/
-rw------- postgres/postgres 262144 2023-04-20 16:20 pg_xact/0000
-rw------- postgres/postgres 229376 2023-05-21 06:50 pg_xact/0004
-rw------- postgres/postgres 262144 2023-05-05 23:32 pg_xact/0002
-rw------- postgres/postgres 262144 2023-04-28 02:18 pg_xact/0001
-rw------- postgres/postgres 262144 2023-05-13 09:45 pg_xact/0003
drwx------ postgres/postgres      0 2023-05-21 06:52 pg_wal/
drwx------ postgres/postgres      0 2023-05-21 06:52 ./pg_wal/archive_status/
drwx------ postgres/postgres      0 2022-10-31 06:27 pg_serial/
drwx------ postgres/postgres      0 2022-10-31 06:27 pg_snapshots/
drwx------ postgres/postgres      0 2022-10-31 06:27 pg_commit_ts/
-rw------- postgres/postgres      3 2022-10-31 06:27 PG_VERSION
drwx------ postgres/postgres      0 2023-05-20 06:59 pg_subtrans/
drwx------ postgres/postgres      0 2023-05-20 22:05 pg_stat/
drwx------ postgres/postgres      0 2023-04-14 06:42 base/
drwx------ postgres/postgres      0 2023-05-20 22:05 base/1/
-rw------- postgres/postgres  24576 2022-10-31 06:27 base/1/3394_fsm
-rw------- postgres/postgres   8192 2022-10-31 06:27 base/1/13321
....

Next, I’ll restore the base dir

postgres@builder-T100:~$ cd  /var/lib/postgresql/12/
postgres@builder-T100:~/12$ ls
main
postgres@builder-T100:~/12$ mv main main.old

postgres@builder-T100:~/12$ mkdir /var/lib/postgresql/12/main

postgres@builder-T100:~/12$ tar xvf /mnt/psqlbackups/2023-05-21/base.tar.gz -C /var/lib/postgresql/12/main
backup_label
tablespace_map
pg_replslot/
...

And the wal files

postgres@builder-T100:~/12$ tar xvf /mnt/psqlbackups/2023-05-21/pg_wal.tar.gz -C /var/lib/postgresql/12/main/pg_wal
00000001000000030000005D
archive_status/00000001000000030000005D.done
00000001000000030000005E

Now start PSQL

builder@builder-T100:~$ sudo systemctl start postgresql.service
builder@builder-T100:~$ sudo systemctl status postgresql.service
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
     Active: active (exited) since Mon 2023-05-22 06:32:41 CDT; 5s ago
    Process: 260601 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 260601 (code=exited, status=0/SUCCESS)

May 22 06:32:41 builder-T100 systemd[1]: Starting PostgreSQL RDBMS...
May 22 06:32:41 builder-T100 systemd[1]: Finished PostgreSQL RDBMS.
builder@builder-T100:~$ sudo systemctl status postgresql.service
● postgresql.service - PostgreSQL RDBMS
     Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
     Active: active (exited) since Mon 2023-05-22 06:32:41 CDT; 9s ago
    Process: 260601 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 260601 (code=exited, status=0/SUCCESS)

May 22 06:32:41 builder-T100 systemd[1]: Starting PostgreSQL RDBMS...
May 22 06:32:41 builder-T100 systemd[1]: Finished PostgreSQL RDBMS.

I saw it crashed, seems permissions related

builder@builder-T100:~$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 down   postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
builder@builder-T100:~$ tail -f /var/log/postgresql/postgresql-12-main.log
2023-05-22 06:00:15.605 CDT [721] LOG:  database system is ready to accept connections
2023-05-22 06:25:52.130 CDT [721] LOG:  received fast shutdown request
2023-05-22 06:25:52.131 CDT [721] LOG:  aborting any active transactions
2023-05-22 06:25:52.132 CDT [721] LOG:  background worker "logical replication launcher" (PID 729) exited with exit code 1
2023-05-22 06:25:52.133 CDT [724] LOG:  shutting down
2023-05-22 06:25:52.143 CDT [721] LOG:  database system is shut down
2023-05-22 06:32:41.346 CDT [260574] FATAL:  data directory "/var/lib/postgresql/12/main" has invalid permissions
2023-05-22 06:32:41.346 CDT [260574] DETAIL:  Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).
pg_ctl: could not start server
Examine the log output.

I fixed and checked the ownership, looks good now

builder@builder-T100:~$ sudo chmod 750 /var/lib/postgresql/12/main
builder@builder-T100:~$ ls -ltra /var/lib/postgresql/12/main
ls: cannot open directory '/var/lib/postgresql/12/main': Permission denied
builder@builder-T100:~$ sudo ls -ltra /var/lib/postgresql/12/main
total 88
-rw-------  1 postgres postgres   88 Oct 31  2022 postgresql.auto.conf
-rw-------  1 postgres postgres    3 Oct 31  2022 PG_VERSION
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_twophase
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_tblspc
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_snapshots
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_serial
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_replslot
drwx------  4 postgres postgres 4096 Oct 31  2022 pg_multixact
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_dynshmem
drwx------  2 postgres postgres 4096 Oct 31  2022 pg_commit_ts
drwx------  9 postgres postgres 4096 Apr 14 06:42 base
drwx------  2 postgres postgres 4096 May 13 09:45 pg_xact
drwx------  2 postgres postgres 4096 May 20 06:59 pg_subtrans
drwx------  2 postgres postgres 4096 May 20 22:05 pg_stat_tmp
drwx------  2 postgres postgres 4096 May 20 22:05 pg_stat
drwx------  2 postgres postgres 4096 May 20 22:05 pg_notify
drwx------  2 postgres postgres 4096 May 21 06:27 global
-rw-------  1 postgres postgres    0 May 21 06:52 tablespace_map
drwx------  4 postgres postgres 4096 May 21 06:52 pg_logical
-rw-------  1 postgres postgres  226 May 21 06:52 backup_label
drwxr-xr-x  4 postgres postgres 4096 May 22 06:30 ..
drwxr-x--- 19 postgres postgres 4096 May 22 06:30 .
drwx------  3 postgres postgres 4096 May 22 06:32 pg_wal
builder@builder-T100:~$

I actually had to change that to 700 (750 did not work)

builder@builder-T100:~$ ls -ltra //var/lib/postgresql/12
total 16
drwx------ 19 postgres postgres 4096 May 22 06:25 main.old
drwxr-xr-x  4 postgres postgres 4096 May 22 06:30 .
drwxr-x--- 19 postgres postgres 4096 May 22 06:30 main
drwxr-xr-x  3 postgres postgres 4096 May 22 06:32 ..
builder@builder-T100:~$ sudo chmod 700 /var/lib/postgresql/12/main
builder@builder-T100:~$ sudo systemctl stop postgresql.service
builder@builder-T100:~$ sudo systemctl start postgresql.service


builder@builder-T100:~$ tail -f /var/log/postgresql/postgresql-12-main.log
Examine the log output.
2023-05-22 06:35:25.565 CDT [283508] LOG:  starting PostgreSQL 12.15 (Ubuntu 12.15-1.pgdg20.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
2023-05-22 06:35:25.565 CDT [283508] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2023-05-22 06:35:25.566 CDT [283508] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-05-22 06:35:25.578 CDT [283513] LOG:  database system was interrupted; last known up at 2023-05-21 06:52:36 CDT
2023-05-22 06:35:25.695 CDT [283513] LOG:  redo starts at 3/5D000028
2023-05-22 06:35:25.698 CDT [283513] LOG:  consistent recovery state reached at 3/5D0D3178
2023-05-22 06:35:25.698 CDT [283513] LOG:  invalid record length at 3/5E0000E8: wanted 24, got 0
2023-05-22 06:35:25.698 CDT [283513] LOG:  redo done at 3/5E0000C0
2023-05-22 06:35:25.721 CDT [283508] LOG:  database system is ready to accept connections

And we can see we are online

builder@builder-T100:~$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

I can of course login and see the backup is solid

builder@builder-T100:~$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
builder@builder-T100:~$ sudo su - postgres
postgres@builder-T100:~$ psql
psql (12.15 (Ubuntu 12.15-1.pgdg20.04+1))
Type "help" for help.

postgres=# \l
                                    List of databases
     Name      |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
---------------+----------+----------+-------------+-------------+-----------------------
 notary_server | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres         +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | harbor=CTc/postgres  +
               |          |          |             |             | instana=c/postgres
 notary_signer | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres         +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | harbor=CTc/postgres  +
               |          |          |             |             | instana=c/postgres
 postgres      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres         +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | instana=CTc/postgres
 registry      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres         +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | harbor=CTc/postgres  +
               |          |          |             |             | instana=c/postgres
 template0     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | instana=c/postgres
 template1     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
               |          |          |             |             | postgres=CTc/postgres+
               |          |          |             |             | instana=c/postgres
 zabbix        | zabbix   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
(7 rows)

Next Steps

If I were to need to use this host, I would have to ensure my hba.conf is set properly, the host itself has firewalls disabled or at least allows 4321 through for Postgres and change the calling services.

The more likely scenario is that the host server crashed and I rebuilt, and I want a point in time snapshot.

My other step would (will) be to setup a crontab to schedule backups, something similar to that which is covered in this SO post. For now, I’m happy with a single point in time.

Summary

Today we covered backing up PostgreSQL 12 using pg_basebackup, sending it to an NFS share, then restoring to a different Linux host. This is a pretty basic DR flow we can build upon later.

PostgreSQL Database DR

Have something to add? Feedback? You can use the feedback form

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes