May 16, 2021 by Daniel F Dickinson5 minutes
An article outlining how to use a Raspberry Pi Model B+ as a PostgreSQL server (requires using external storage).
In combination with the Raspberry Pi OS for a server and Using XCA to create private SSL certificates articles, this article describes setting up a Raspberry Pi Model B+ as a PostgreSQL server with external storage.
This will only handle low volumes of requests per second, so is not a good choice for acting as the database for things like file synchronization programs (like Nextcloud, when used for file sync).
sudo lvcreate -n postgres -L 60G vg1
— assuming the server setup described
in the mentioned article. You also may want to use a different size than 60G
depending on how much data you expect to have. If you’ve been following along and
have space available for allocation you should be able to grow the volume and
filesystem should the need arise.
sudo mkfs.ext4 -E lazy_itable_init=0,lazy_journal_init=0 /dev/vg1/postgres
— formats the volume fully before returning control (without the ‘-E’ options,
Linux will use lazy init which will use background cycles and I/O to complete
the task, but will return immediately. It is not as safe and the Pi doesn’t
really have the resources to operate well with the background processing going
on).
sudo mkdir -p /var/lib/postgresql
sudoedit /etc/fstab
Add a line such as:
/dev/vg1/postgres /var/lib/postgresql ext4 defaults,relatime,noexec 1 1
sudo mount -a
— should complete with no errors
df -h
should show /dev/mapper/vg1-postgres
mounted on
/var/lib/postgresql
sudo apt install -y postgresql postgresql-client
sudo ss -ltpn
should should show user postgres with localhost listeners on
port 5432 (e.g. 127.0.0.1:5432 and [::1]:5432 should be reported in that
command).
sudo systemctl stop postgresql
sudoedit /etc/postgresql/11/main/conf.d/05-scram-password-encryption.conf
password_encryption = scram-sha-256
The server private key and server certificate are the ones you created following the XCA guide mentioned above. You will need to substitute with your actual names of course.
/etc/ssl/private/pisql.use-your-domain.example.com.key
sudo chgrp ssl-cert /etc/ssl/private/pisql.use-your-domain.example.com.key
sudo chmod 0640 /etc/ssl/private/pisql.use-your-domain.example.com.key
/etc/ssl/certs/pisql.use-your-domain.example.com.crt
sudoedit /etc/postgresql/11/main/conf.d/10-ssl-cert-key.conf
and add
lines such as:
ssl_cert_file = '/etc/ssl/certs/pisql.use-your-domain.example.com.crt'
ssl_key_file = '/etc/ssl/private/pisql.use-your-domain.example.com.key'
Save and exit
sudo systemctl start postgresql
sudo pg_conftool show ssl_cert_file
— Should report the certificate
filename you configuredsudo pg_conftool show ssl_key_file
— Should report key filename you
configuredsudo systemctl stop postgresql
/etc/postgresql-common/root.crt
and make sure is owned by root:root and has permissions 0644.sudoedit /etc/postgresql/11/main/conf.d/50-listen-all-interfaces.conf
and
a line such as:
listen_addresses = '*'
Save and exit
Verify if you wish (e.g. start postgresql, check listening ports using ss
and configuration options using pg_conftool
)
Allow traffic in through the firewall
sudo ufw allow in on eth0 proto tcp from any to any port 5432
It is not enough to listen for connections, PostgreSQL also needs to be configured what connections to accept.
sudoedit /etc/postgresql/11/main/pg_hba.conf
Enter lines such as:
hostssl all all 0.0.0.0/0 scram-sha-256
hostssl all all ::/0 scram-sha-256
This tell PostgreSQL to all allow SSL network connections for any database and any user from any address provided the user is able to authenticate using their ‘scram-sha-256’ encoded password.
sudo systemctl start postgresql
sudo systemctl status postgresql
— it should report ‘active (exited)’ and
‘status=0/SUCCESS`
The following commands should complete without errors:
sudo su - postgres
createuser --createdb --pwprompt testuser
createdb -U testuser -h \<address-of-your-pi> testdb "\c sslmode=require"
exit
psql -U testuser postgresql://\<address-of-your-pi>:5432/testdb?sslmod=require
\l
\q
sudo su - postgres
dropdb testdb
dropuser testuser
exit
sudo su - postgres
mkdir restic-files
cd restic-files
chmod 700 .
touch password-file
chmod 600 password-file
sensible-editor password-file
In the editor, add a strong password (e.g. 30 alphanumeric and special characters), then save and close (having a file with the password not ideal, but avoiding it is rather complicated, and out of scope for this article).
If using SFTP for backups, create a passwordless SSH keypair using:
ssh-keygen -t rsa -f restic-postgres@piserver -C restic-postgres@piserver -N ''
restic-postges@piserver.pub
to you destination’s
`authorized_keys`` file.(assuming you have configured, ~/.ssh/config
so that
restic-postgres@backupserver.example.com
uses the
restic-postgres@piserver
created above:
pg_dumpall -c --if-exists | restic -r sftp:restic-postgres@backupserver.example.com:/path/to/repo --password-file ./password-file backup --stdin --stdin-filename postgresql.sql
Now create a crontab entry to do this every four hours:
crontab -e
Add an entry such as:
23 */4 * * * pg_dumpall -c --if-exists 2>/dev/null | restic -r sftp:restic@backupserver.example.com:/path/to/repo --password-file ./password-file backup --stdin --stdin-filename postgresql.sql --cleanup-cache --quiet 2>&1 | logger -t restic
Save and exit the editor
exit
Your server should now be ready for use.