Skip to content

Backup & DR

Consolidated backup and restore reference. Service-specific pages contain fuller context - this page covers the overall DR order and quick-reference commands for each critical data store.


If the homelab needs to be rebuilt from scratch, restore in this sequence.

Step 1. VPS first. Keycloak and Pangolin must be online before any service that depends on OIDC authentication. Without Keycloak, no service can authenticate users. Without Pangolin, external access to Immich, Jellyfin, OpenCloud, and Planka is severed.

Step 2. TrueNAS pool. Import the tank pool. All service data lives under tank/apps/ and tank/configs/. Datasets are unencrypted.

Step 3. Services. Restore in any order after the pool is online. Each service mounts its own dataset path and is independent of the others.


Runs on the VPS at /opt/keycloak/. Back up before any Keycloak version upgrade.

Terminal window
# Backup - PostgreSQL dump
docker exec keycloak-postgres pg_dump -U keycloak keycloak \
> /opt/keycloak/backup-$(date +%Y%m%d).sql
# Restore
docker exec -i keycloak-postgres psql -U keycloak keycloak \
< /opt/keycloak/backup-YYYYMMDD.sql

Start keycloak-postgres first, restore, then start keycloak. Verify the OIDC discovery endpoint responds before bringing up dependent services.

Terminal window
curl -s https://auth.wighttrash.uk/realms/wighttrash/.well-known/openid-configuration

See Keycloak for upgrading and the break-glass kcadmin account.


All data lives on TrueNAS. Two datasets to preserve:

DatasetContents
tank/apps/immich/dataPhoto and video library
tank/apps/immich/pgDataPostgreSQL database (pgvecto)

The photo library is the critical backup target. If pgData is lost but data is intact, Immich can rescan and rebuild the database (albums, faces, and memories are lost but files are not).

Terminal window
# Backup database
sudo docker exec ix-immich-pgvecto-1 pg_dump -U immich immich \
> /mnt/tank/configs/immich-backup-$(date +%Y%m%d).sql
# Restore database
cat /mnt/tank/configs/immich-backup-YYYYMMDD.sql | \
sudo docker exec -i ix-immich-pgvecto-1 psql -U immich immich

Database user: immich. Database name: immich. Container: ix-immich-pgvecto-1. See Immich for the OAuth recovery procedure.


Data lives at /mnt/tank/configs/planka/. Two components: PostgreSQL database and uploaded file attachments.

Terminal window
# Backup database
docker exec planka-db pg_dump -U planka planka \
> /mnt/tank/configs/planka/backup-$(date +%Y%m%d).sql
# Backup file attachments
tar czf /mnt/tank/configs/planka/attachments-backup-$(date +%Y%m%d).tar.gz \
-C /mnt/tank/configs/planka attachments user-avatars background-images favicons
# Restore database
docker stop planka
cat /mnt/tank/configs/planka/backup-YYYYMMDD.sql | \
docker exec -i planka-db psql -U planka planka
# Restore files
tar xzf /mnt/tank/configs/planka/attachments-backup-YYYYMMDD.tar.gz \
-C /mnt/tank/configs/planka
# Fix permissions and restart
chown -R 1000:1000 /mnt/tank/configs/planka/{favicons,user-avatars,background-images,attachments}
docker start planka

See Planka for the full install and database restore procedure.


Data lives at /mnt/tank/configs/opencloud/. Two directories:

PathContents
/mnt/tank/configs/opencloud/dataUser files and OpenCloud metadata
/mnt/tank/configs/opencloud/configConfiguration including csp.yaml
Terminal window
# Backup config directory
tar czf /mnt/tank/opencloud-config-backup-$(date +%Y%m%d).tar.gz \
/mnt/tank/configs/opencloud/config
# ZFS snapshot of the full data directory (preferred for consistency)
zfs snapshot tank/configs/opencloud@$(date +%Y%m%d)
# List snapshots
zfs list -t snapshot | grep opencloud
# Roll back to a snapshot
zfs rollback tank/configs/opencloud@YYYYMMDD

See OpenCloud for restart commands and Keycloak role requirements.


The tank pool is RAIDZ1 across 3 drives. One drive failure is tolerated. Datasets are unencrypted.

Terminal window
# Pool status
zpool status tank
# Manual scrub (scheduled automatically every Sunday at 00:00)
zpool scrub tank
# Export pool (before physical move to new hardware)
zpool export tank
# Import pool (on new hardware)
zpool import tank

Monitor pool status in TrueNAS Storage - Pools for any errors or degraded state. A degraded pool still functions but has no redundancy - replace failed drives promptly.