Single Machine Backup & Restore Guide
Guide to back up and restore PostgreSQL, MinIO, and Keycloak on an OpenG2P single machine deployment.
1. Overview
This document explains how to back up and restore the three critical stateful components running on the OpenG2P single machine deployment: PostgreSQL, MinIO, and Keycloak. It covers what each component is, why it needs a backup, the exact commands to run, and how to verify the restore worked.
1.1 What Needs to be backed up
Not everything in the cluster needs a backup. Only components that store persistent data matter. Stateless pods like <your-app>, <your-app> frontend, and Redis are automatically restarted by Kubernetes if they crash — no backup needed.
PostgreSQL
<postgresql-pod>
All application databases — application databases
Critical
PostgreSQL
<<keycloak-pg-secret>-pod>
Keycloak's own database
Critical
MinIO
<minio-pod>
Uploaded files, form attachments, documents
High
Keycloak
<keycloak-pod>
Realm config — users, clients, roles, SSO settings
High
1.2 Restore order
When restoring a fresh system, always follow this order. Keycloak depends on its database existing first.
Restore PostgreSQL (<pg-secret>)
Restore PostgreSQL (<keycloak-pg-secret>)
Restore MinIO buckets
Restore Keycloak realms
Restart all pods
Never restore Keycloak realm before PostgreSQL. Keycloak needs its database to be running before the realm import can succeed.
2. Prerequisites
2.1 SSH access to node
All backup commands are run on the node itself. Connect from your laptop using:
Once connected, switch to root:
2.2 Create backup directories
Run once on the node to create the backup folder structure:
Verify with: ls /opt/backups/ — you should see three folders: postgres, minio, keycloak
2.3 Install MinIO client (mc)
The mc tool is needed for MinIO backup. Install it once on the node:
Verify installation:
2.4 Credentials reference
Keep these credentials secure. They are needed for backup and restore commands.
<pg-secret>
<pg-secret>
postgres
<postgres-password>
<keycloak-pg-secret>
<keycloak-pg-secret>
postgres
<keycloak-postgres-password>
MinIO
<minio-secret>
admin
<minio-secret-key>
Keycloak (commons)
<keycloak-secret>
admin
<keycloak-admin-password>
To re-fetch any password from the cluster: kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data.<key>}' | base64 -d && echo
3. Taking backups
3.1 PostgreSQL backup
PostgreSQL stores all application data. We use pg_dumpall which exports every database, table, user, and permission into a single compressed SQL file. This file can recreate everything from scratch on a fresh PostgreSQL instance.
Backup <pg-secret> (main databases)
This backs up: <app-database>, <app-database>, odkdb, <app-db>, commons_services_iam, commons_services_master_data, <app-database>.
Verify the file was created:
Expected output: a .sql.gz file of around 150-200KB. If the file is 0 bytes, the backup failed.
Backup <keycloak-pg-secret>
This backs up the Keycloak database separately.
Verify:
Expected: a file of around 30-50KB.
3.2 MinIO backup
MinIO stores all uploaded files and attachments. We use the mc mirror command which copies all buckets and their contents to a local folder.
Configure mc alias (run once)
Run the mirror backup
Verify:
If MinIO has no data yet, the folder will be empty. That is normal — the process is correct and will capture files once users start uploading.
3.3 Keycloak realm export
Keycloak organises everything into realms. We export each realm as a JSON file using the Keycloak Admin API. The export includes all clients, roles, users, and SSO configurations.
Your cluster has two realms: staff and master.
Export staff realm
Export master realm
Verify both files:
Expected: staff realm around 80KB and master realm around 52KB. Files smaller than 1KB mean the export failed.
3.4 Copy backups to laptop
Run this command on your laptop (not on the node) to pull all backup files locally:
Verify on laptop:
4. Automating with cron job
A cron job is a scheduled task on Linux. Instead of running backup commands manually every day, a cron job runs them automatically at a fixed time — in our case, every day at 2 AM.
4.1 Create the backup script
On the node, create a single script that runs all backups:
Make the script executable:
4.2 Schedule with cron
Open the crontab editor:
Add this line at the bottom of the file:
This means: run the backup script every day at 2:00 AM.
Verify the cron job was saved:
To test the script manually without waiting for 2 AM: bash /opt/backup-scripts/daily_backup.sh
5. Restore procedures
Use these procedures when the system needs to be recovered. Always restore in the order shown — PostgreSQL first, Keycloak last.
5.1 Restore PostgreSQL
This procedure restores all application databases from a backup file. Use this when PostgreSQL data is lost or corrupted.
Step 1 — Copy backup file into the pod
Step 2 — Restore all databases
You will see errors like 'role already exists' — these are normal and safe to ignore. The data restores correctly despite these messages.
Step 3 — Verify all databases are back
kubectl exec -n <namespace> <postgresql-pod> -- \
You should see all these databases in the list:
commons_services_iam
commons_services_master_data
keycloak
<app-database>
<app-database>
<app-database>
odkdb
<app-db>
Restore keycloak postgreSQL
5.2 Restore MinIO
This procedure restores all MinIO buckets and files from the backup folder.
Step 1 — Configure mc alias (if not already done)
Step 2 — Mirror backup back to MinIO
Step 3 — Verify buckets are restored
✓ All buckets that existed at backup time should now appear in the list.
5.3 Restore keycloak realms
This procedure reimports the Keycloak realm configuration — clients, roles, users, and SSO settings — from the JSON backup files.
Step 1 — Get auth token
Step 2 — Copy realm JSON into the pod
Step 3 — Import the realm
Repeat Step 2 and Step 3 for the master realm using commons-realm-master-2026-04-16.json
Last updated
Was this helpful?