Databases Azure

repmgr PostgreSQL Replication Manager on Ubuntu 24.04 on Azure User Guide

| Product: repmgr PostgreSQL Replication Manager on Ubuntu 24.04 on Azure

Overview

This guide covers the deployment and use of repmgr on PostgreSQL 17 on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. repmgr is the long established open source toolset from EDB for managing PostgreSQL streaming replication and automatic failover. This image is a fully configured PostgreSQL 17 primary node: repmgr is installed, the primary is registered as node 1, and the repmgrd monitoring daemon runs under systemd. It gives you a proven starting point for a highly available PostgreSQL cluster — clone standby nodes against this primary, register them, and repmgr manages promotion and failover.

Both PostgreSQL 17 and the postgresql-17-repmgr package are installed from the official PostgreSQL PGDG repository. PostgreSQL is configured for streaming replication (wal_level = replica, WAL senders and replication slots, wal_log_hints for pg_rewind, and shared_preload_libraries = 'repmgr' so repmgrd can run).

Security by design — no baked credential. There are two built in roles and neither has a password baked into the image. The postgres superuser is password less by construction. The dedicated repmgr role — the identity repmgr, repmgrd, and standby nodes authenticate as — is created with no password. On first boot each VM generates a unique password for the postgres superuser, a unique password for the repmgr role, and a unique self signed TLS server certificate; writes a .pgpass so repmgrd can authenticate; rewrites the repmgr connection string to this VM's own address; re-registers the primary; starts repmgrd; and writes the root only file /root/repmgr-credentials.txt. Remote clients and standby nodes are accepted only over TLS with scram-sha-256; on box administration stays password less through the local unix socket.

What is included:

  • PostgreSQL 17 from the official PGDG repository, running under systemd as postgresql.service

  • The postgresql-17-repmgr package (repmgr 5.5), with this node registered as node 1, the primary

  • repmgrd running as repmgrd.service, monitoring the primary and ready to manage standby promotion and failover

  • Per VM passwords for the postgres superuser and the repmgr role, plus a per VM TLS certificate, all generated on first boot and written to a root only credentials file

  • pg_hba.conf configured so standby nodes and remote clients connect only over TLS with scram-sha-256, while local access stays password less via the unix socket

  • Unattended security upgrades left enabled so the appliance keeps receiving patches

Prerequisites

  • Active Azure subscription, an SSH public key, and a VNet + subnet in the target region

  • Subscription to this listing on Azure Marketplace

  • A Network Security Group allowing TCP 22 (administration) and TCP 5432 (PostgreSQL / repmgr replication). Standby nodes and application clients reach the primary on 5432. In production, restrict 5432 to your database and application subnets.

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for development and light workloads. For production databases, choose a larger size such as Standard_E2s_v5 or above.

Deploy the virtual machine

Create the VM from the image, opening SSH and the PostgreSQL port to your own network:

az vm create \
  --resource-group my-rg \
  --name repmgr-primary \
  --image <this-marketplace-image> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group my-rg --name repmgr-primary --port 5432 --priority 900

Retrieve your per VM credentials

On the first boot the VM generates its own passwords and TLS certificate, writes the .pgpass for the repmgr role, and re-registers the primary with this VM's address. SSH in and read the root only credentials file (replace <public-ip> with your VM's public IP when connecting from a client):

# On the primary VM — the secrets are unique to each VM, generated on first boot.
sudo cat /root/repmgr-credentials.txt
# Use postgres.password as <POSTGRES_PASSWORD> and repmgr.password as <REPMGR_PASSWORD>
# when you connect from a client or a standby at <public-ip>.

The file is mode 0600, owned by root, and lists the postgres superuser password, the repmgr role password, the resolved host, and a ready to follow standby join walkthrough. Nothing is baked into the image — every deployed VM has its own passwords and certificate.

Terminal showing the per VM credentials file at /root/repmgr-credentials.txt, mode 600 owned by root, listing the postgres host and port, the postgres superuser password (masked), the repmgr role and password (masked), the repmgr database, and the node id and node name that first boot generated for this VM

Confirm the services are healthy

SSH into the VM and confirm PostgreSQL 17 and repmgr are installed and running:

sudo systemctl is-active postgresql
sudo -u postgres psql -tAc "SELECT version();"
/usr/lib/postgresql/17/bin/repmgr -V

You should see active, the PostgreSQL 17.10 server banner, and repmgr 5.5.0. On a first booted VM repmgrd.service is also active — it is started once first boot has written the per VM credentials.

Terminal showing postgresql.service and postgresql@17-main.service active, repmgrd.service active and running, PostgreSQL listening on port 5432, and the PostgreSQL 17.10 server version banner, confirming the database and the repmgr daemon are both healthy

Confirm the replication configuration

repmgr requires PostgreSQL to be configured for streaming replication. This image sets that up already; confirm it:

sudo -u postgres psql -tAc "SHOW shared_preload_libraries;"
sudo -u postgres psql -tAc "SHOW wal_level;"
sudo -u postgres psql -tAc "SHOW max_wal_senders;"

shared_preload_libraries includes repmgr (required for repmgrd), wal_level is replica, and max_wal_senders is 10 — enough headroom for multiple standby nodes.

Show the cluster

repmgr keeps a record of every node in the cluster. On the primary, repmgr cluster show lists them (run as the postgres user, which authenticates the repmgr role through the .pgpass first boot wrote):

# Run on the primary (node at <public-ip>).
sudo -u postgres /usr/lib/postgresql/17/bin/repmgr -f /etc/repmgr.conf cluster show

With only the primary deployed you see a single row: node 1, role primary, status * running. As you add standby nodes they appear here too.

Terminal showing repmgr cluster show output: a single row for node ID 1 named pg_primary, role primary, status star running, priority 100, timeline 1, and its connection string, confirming the primary is registered and healthy

Check node health

repmgr node check reports the replication readiness of a node — role, WAL archiving, replication slots, and data directory:

# Run on the primary (node at <public-ip>).
sudo -u postgres /usr/lib/postgresql/17/bin/repmgr -f /etc/repmgr.conf node check

Every line reads OK. On the primary the replication lag, upstream connection, and downstream server checks report N/A or none, as expected for a node with no standbys yet.

Terminal showing repmgr node check output for node pg_primary: server role OK node is primary, replication lag OK, WAL archiving OK, upstream connection OK, downstream servers OK, replication slots OK, and configured data directory OK

Add a standby node

To build a highly available cluster, deploy a second cloudimg repmgr VM and clone it from this primary. On the primary, read the repmgr role password from /root/repmgr-credentials.txt. Then, on the new standby VM, let it authenticate to the primary and clone (replace <public-ip> with the primary's public IP and <REPMGR_PASSWORD> with the primary's repmgr password):

# On the STANDBY VM. Give this node a unique node_id (e.g. 2) in /etc/repmgr.conf first.
echo "<public-ip>:5432:*:repmgr:<REPMGR_PASSWORD>" | sudo -u postgres tee -a /var/lib/postgresql/.pgpass
sudo -u postgres chmod 600 /var/lib/postgresql/.pgpass
# Dry run first, then clone and register:
sudo -u postgres /usr/lib/postgresql/17/bin/repmgr -h <public-ip> -U repmgr -d repmgr -f /etc/repmgr.conf standby clone --dry-run
sudo -u postgres /usr/lib/postgresql/17/bin/repmgr -h <public-ip> -U repmgr -d repmgr -f /etc/repmgr.conf standby clone
sudo systemctl start postgresql
sudo -u postgres /usr/lib/postgresql/17/bin/repmgr -f /etc/repmgr.conf standby register

Run repmgr cluster show on the primary again and the standby appears as a second row with role standby following node 1. Repeat for further standbys.

Connect application clients over TLS

Application clients connect to the primary as the postgres superuser over TLS. Replace <public-ip> with the primary's public IP and <POSTGRES_PASSWORD> with the value from the credentials file:

PGPASSWORD='<POSTGRES_PASSWORD>' psql "host=<public-ip> port=5432 dbname=postgres user=postgres sslmode=require" -c "SELECT now();"

The connection is encrypted with the per VM certificate first boot generated. Point your application's read/write traffic at the primary; direct read only reporting traffic at standby nodes once you add them.

Automatic failover with repmgrd

repmgrd is already running on the primary and is configured for automatic failover (failover = automatic in /etc/repmgr.conf). Once you have registered one or more standby nodes, repmgrd monitors the primary and, if it fails, promotes the most suitable standby and tells the remaining standbys to follow the new primary. You can inspect repmgrd's decisions in its log:

sudo journalctl -u repmgrd --no-pager -n 50

For production, review the repmgr documentation on witness nodes, location, and priority to tune promotion behaviour, and place standbys in a different Azure availability zone from the primary.

Security notes

  • No baked credential. Both the postgres superuser and the repmgr role ship with no password; each VM generates its own on first boot. The credentials file is 0600 root:root.

  • TLS everywhere off box. pg_hba.conf accepts standby replication, the repmgr database, and application clients from the network only over TLS (hostssl) with scram-sha-256. A per VM self signed certificate is generated on first boot. For production, replace it with a certificate from your own CA.

  • Network. Keep the Azure NSG tight — allow 5432 only from your database, application, and standby subnets. The NSG is the first layer; TLS and the per VM password are the second and third.

  • Rotating a password. To rotate the repmgr role password, ALTER ROLE repmgr WITH PASSWORD '...' on the primary, update each node's .pgpass, and reload repmgrd.

Troubleshooting

  • repmgr cluster show cannot connect — confirm /var/lib/postgresql/.pgpass exists (mode 600, owned postgres) with the repmgr password, and that ssl = on in postgresql.conf. First boot writes both; check /var/log/cloudimg-firstboot.log.

  • A standby will not clone — confirm the primary's NSG allows 5432 from the standby, that the standby's .pgpass has the primary's repmgr password, and run standby clone --dry-run to surface the exact failure.

  • repmgrd inactive — on a fresh VM repmgrd starts only after first boot has written the credentials. Check systemctl status repmgrd and /var/log/cloudimg-firstboot.log; the daemon is gated on /var/lib/cloudimg/repmgr-ready.

Support

This image is maintained by cloudimg with 24/7 support. For assistance, contact us via the cloudimg listing on Azure Marketplace.