How to change PostgreSQL's data directory on Linux
There comes a time when you have to restore a relatively large database locally. Most likely, you’ve partitioned your disk, and your root
partition got the thick end of it, 50 GB if you were generous. Let’s assume that that’s not nearly enough for the database you’re about to restore. At the same time, your /home
partition got the rest of the disk space you had available.
You can always resize these two partitions, but then you would have back up your /home
directory, unmount it or find a Live USB and tamper with them. If you don’t have the time, or the desire, or even a backup disc, you can always change the location where postgresql
stores its data.
The following instructions are a love letter to all those lost souls who find themselves in this situation and forget to check the status of SELinux, as well as to my future self who’ll most likely have to do it again. Considering this is mostly a dump of my bash history that has everything and anything, I hope this exact procedure works for you. If not, feel free to contact me and we’ll update it together.
Procedure
A fresh install is the easiest to change, but let’s assume you have some databases locally you don’t want to lose, just move them and restore the large database next to them. The steps are more or less the same anyway.
data_directory
and config_file
Before you start anything, locate the postgresql
’s configuration file and its data directory:
$ sudo su - postgres
[postgres@host ~]$ psql
Password for user postgres:
psql (12.6)
Type "help" for help.
postgres=# SHOW config_file;
config_file
-----------------------------------
/var/lib/pgsql/data/postgresql.conf
(1 row)
postgres=# SHOW data_directory;
data_directory
-------------------
/var/lib/pgsql/data
(1 row)
Stop the systemd
service
Stop the postgresql
systemd
service:
systemctl stop postgresql.service
New location
Create a directory where you have enough disk space available (in this case, it’s the /home
directory), grant the postgres
user ownership and permissions over it and copy the original data directory to the new location (the key is to preserve the same ownership and permissions structure):
mkdir /home/pgdata
chown postgres:postgres /home/pgdata
chmod 700 /home/pgdata
rsync -av /var/lib/pgsql/data/ /home/pgdata/data
postgresql
configuration
Open the postgresql.conf
file in the new location and update the data_directory
variable, setting it to the new location where your data was moved:
vim /home/pgdata/data/postgresql.conf
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
# The default values of these variables are driven from the -D command-line
# option or PGDATA environment variable, represented here as ConfigDir.
data_directory = '/home/pgdata/data' # use data in another directory
# (change requires restart)
#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file
# (change requires restart)
#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file
systemd
configuration
Do the same thing with the postgresql.service
’s systemd
configuration file:
vim /lib/systemd/system/postgresql.service
# ...
Environment=PGDATA=/home/pgdata/data
# ...
Once you’re done editing the systemd
configuration, reload it and start the service:
systemctl daemon-reload
systemctl start postgresql.service
systemctl status postgresql.service
SELinux
If you’re receiving some vague Permission denied
errors, check whether or not you have SELinux enabled:
cat /sys/fs/selinux/enforce
1
If the result is 1
, then SELinux is in enforcing
mode. To temporarily set it to permissive
mode (0
), run:
setenforce 0
You can try starting the postgresql.service
again. If the process has started successfully, stop it, and tell SELinux to apply the same context to the new location. Then you can return SELinux to enforcing
mode
semanage fcontext --add --equal /var/lib/pgsql /home/pgdata
restorecon -rv /home/pgdata
setenforce 1
Then you should be able to start the postgresql.service
without any errors
systemctl start postgresql.service
systemctl status postgresql.service
Confirmation
To confirm the new location and configuration is used, rerun the first step:
➜ sudo su - postgres
[postgres@lenovo ~]$ psql
Password for user postgres:
psql (12.6)
Type "help" for help.
postgres=# SHOW data_directory;
data_directory
-------------------
/home/pgdata/data
(1 row)
postgres=# SHOW config_file;
config_file
-----------------------------------
/home/pgdata/data/postgresql.conf
(1 row)