PostgreSQL 18 & Patroni — Install & Configure
Run everything on this page on the three database nodes — pg-sv01, pg-sv02, pg-sv03.
Install PostgreSQL 18 and Patroni
Add the official PostgreSQL (PGDG) repository, then install PostgreSQL 18 and Patroni:
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
| sudo gpg --dearmor -o /etc/apt/keyrings/pgdg.gpg
. /etc/os-release
echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] https://apt.postgresql.org/pub/repos/apt ${VERSION_CODENAME}-pgdg main" \
| sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt-get update
sudo apt-get install -y postgresql-18 postgresql-client-18 patroni python3-etcd
⚠️ Don't skip
python3-etcd. Without it (e.g. if you install Patroni with--no-install-recommends), Patroni cannot load the etcd backend and fails to start with:Can not find suitable configuration of distributed configuration store. Available implementations: consul, kubernetesInstallingpython3-etcdmakes theetcd/etcd3backends available. (We use the etcd3 backend, since etcd 3.5 disables the legacy v2 API by default.)
Remove the distro's default cluster
The Debian/Ubuntu package automatically creates and starts a main cluster on port 5432. Patroni must own that port and its own data directory, so drop the default cluster:
sudo pg_dropcluster --stop 18 main
sudo systemctl disable --now postgresql
sudo install -d -o postgres -g postgres -m 0700 /var/lib/postgresql/18/patroni
sudo install -d -o postgres -g postgres -m 0755 /etc/patroni
Firewall (UFW)
Allow PostgreSQL and the Patroni REST API from the other DB nodes and the HAProxy node:
for p in 10.100.100.104 10.100.100.105 10.100.100.106 10.100.100.103; do
sudo ufw allow from $p to any port 5432 proto tcp
sudo ufw allow from $p to any port 8008 proto tcp
done
Patroni configuration
Create /etc/patroni/patroni.yml on each node. Only name and the two connect_address lines differ per node — set them to that node's hostname and IP.
scope: pg-cluster
namespace: /service/
name: pg-sv01 # <-- pg-sv02 / pg-sv03 on the other nodes
restapi:
listen: 0.0.0.0:8008
connect_address: 10.100.100.104:8008 # <-- this node's IP
authentication:
username: admin
password: ChangeMe_PatroniREST # protects unsafe REST methods only
etcd3:
hosts:
- 10.100.100.104:2379
- 10.100.100.105:2379
- 10.100.100.106:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
max_connections: 100
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 128MB
wal_log_hints: "on" # required for pg_rewind
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- local all all trust
- host all all 127.0.0.1/32 scram-sha-256
- host all all 10.100.100.0/24 scram-sha-256
- host replication replicator 127.0.0.1/32 scram-sha-256
- host replication replicator 10.100.100.0/24 scram-sha-256
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.100.100.104:5432 # <-- this node's IP
data_dir: /var/lib/postgresql/18/patroni
bin_dir: /usr/lib/postgresql/18/bin
pgpass: /var/lib/postgresql/.pgpass_patroni
authentication:
superuser:
username: postgres
password: ChangeMe_Postgres
replication:
username: replicator
password: ChangeMe_Replicator
rewind:
username: rewind_user
password: ChangeMe_Rewind
parameters:
password_encryption: scram-sha-256
watchdog:
mode: "off" # enable if you provide /dev/watchdog
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
sudo chown postgres:postgres /etc/patroni/patroni.yml
sudo chmod 0600 /etc/patroni/patroni.yml
A few notes on the important settings:
bootstrap.dcsis written to etcd once, on first bootstrap; it is the cluster-wide source of truth thereafter (edit it later withpatronictl edit-config, not the file).wal_log_hints: "on"+use_pg_rewind: truelet a failed primary rejoin quickly without a full re-clone.ttl: 30is the leader lease — a dead primary's lock expires after ~30 s, which is the upper bound on failover detection time.watchdog: mode: "off"because our VMs have no/dev/watchdog; on bare metal with a real watchdog, set it toautomaticfor stronger split-brain protection.
systemd service
Create /etc/systemd/system/patroni.service on each node:
[Unit]
Description=Patroni PostgreSQL HA
After=network-online.target etcd.service
Wants=network-online.target
[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/bin/patroni /etc/patroni/patroni.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable patroni
Don't start it yet — the start order matters, and we cover it on the next page.
No comments to display
No comments to display