This episode secures the pgBackRest transport path: creating a dedicated pgbackrest SSH user with key authentication, configuring hosts and SSH options in the config, and networking rules — never expose the backup server to the public and use a VPN or tunnel for remote connections. This is half of the backup system's security.

In episode 12 we moved the repository to another host and object storage. Every inter-host connection goes over SSH — and sloppily configured SSH is the most common entry point for attackers. In episode 13 we close that door: a dedicated user, key authentication, strict SSH options, and network rules that ensure the backup server is never exposed.
Remember the principle from episode 11: encryption protects data at rest. SSH protects data in transit. A serious backup system needs both.
Using postgres for inter-host SSH is risky: one key opens access to both the database and the repository at once. The best practice is a dedicated user named pgbackrest whose access is restricted to backup tasks only.
sudo useradd --create-home --shell /bin/bash pgbackrest
sudo mkdir -p /var/lib/pgbackrest
sudo chown pgbackrest:pgbackrest /var/lib/pgbackrestsudo -u postgres mkdir -p /home/postgres/.ssh
sudo -u postgres ssh-keygen -t ed25519 -N "" -f /home/postgres/.ssh/pgbackrest_keyCopy the public key to the repository host:
sudo -u pgbackrest mkdir -p /home/pgbackrest/.ssh
echo "ssh-ed25519 AAAA...pgbackrest_key.pub" | sudo -u pgbackrest tee -a /home/pgbackrest/.ssh/authorized_keys
sudo chmod 700 /home/pgbackrest/.ssh
sudo chmod 600 /home/pgbackrest/.ssh/authorized_keysNote
Key authentication is mandatory — never rely on SSH passwords for automation. Passwords can't be automated securely and widen the attack surface. A specially generated key (not your personal key) also makes auditing and separate revocation easier.
pgBackRest uses the *host* options to set the user, port, and key file:
[global]
repo1-host = backup01.internal
repo1-host-user = pgbackrest
repo1-host-port = 22
repo1-host-key = /home/postgres/.ssh/pgbackrest_key
[main]
pg1-host = db01.internal
pg1-host-user = pgbackrest
pg1-host-key = /home/postgres/.ssh/pgbackrest_keyrepo1-host-user / pg1-host-user — the SSH user for each host.repo1-host-key / pg1-host-key — the private key file used.repo1-host-port — the SSH port if it isn't 22.With pg1-host, the database itself is also accessed via SSH — a common pattern when pgBackRest runs on a host separate from the database (for example a central backup server backing up many databases).
Special SSH connection requirements (timeout, keepalive, tunneling) are set via an SSH config file pointed to by the repo1-host-config / pg1-host-config options:
sudo -u postgres cat >> /home/postgres/.ssh/pgbackrest_config << 'EOF'
Host backup01.internal
User pgbackrest
IdentityFile /home/postgres/.ssh/pgbackrest_key
ServerAliveInterval 30
ServerAliveCountMax 4
Compression yes
EOF[global]
repo1-host-config = /home/postgres/.ssh/pgbackrest_configThis gives you full control over SSH behavior — keepalive for long connections, compression for slow links — without touching the system SSH config.
The backup server holds all production data — it should be one of the most protected hosts in your infrastructure, not the easiest to reach. The basic rules:
ss -tlnp | grep -v "127.0.0.1"The output should show that no service is listening on a public interface.
If the backup host is in a different location (another cloud, a separate data center, or across regions), don't open SSH directly to the internet. Two safe patterns:
With these patterns, backup connections run over an already-encrypted and authenticated channel — not raw SSH crossing the internet.
Warning
Exposing the backup server's SSH to the internet is one of the easiest ways to find yourself in brute-force logs. Always use a VPN/tunnel for remote connections, restrict source IPs in the firewall, and make sure sshd only accepts key authentication (PasswordAuthentication no).
After everything is configured, verify:
sudo -u postgres ssh -i /home/postgres/.ssh/pgbackrest_key backup01.internal echo ok
sudo -u postgres pgbackrest --stanza=main check
sudo -u postgres pgbackrest --stanza=main backup --type=fullA successful check proves the entire SSH chain works. For deeper auditing, enable verbose logging for a moment:
sudo -u postgres pgbackrest --stanza=main --log-level-console=debug checkKey takeaways:
pgbackrest SSH user, not postgres for everything.repo1-host-user, repo1-host-key, repo1-host-port; advanced options via repo1-host-config.In the next episode we'll watch over the backup system: monitoring & metrics — Prometheus integration with pgbackrest_exporter, using pgbackrest info --output=json in scripts, and alerting for failed, late (deadline-missed), and stuck-WAL-archiving backups. An unmonitored system is a system that fails silently!