--- myst: html_meta: "description": "Back up and restore a cdk8s-plone deployment by protecting the PostgreSQL database that holds the Plone content." "property=og:description": "Back up and restore a cdk8s-plone deployment by protecting the PostgreSQL database that holds the Plone content." "property=og:title": "Back up and restore" "keywords": "Plone, cdk8s, Kubernetes, backup, restore, PostgreSQL, CloudNativePG, pg_dump, RelStorage" --- # Back up and restore This guide shows you how to back up and restore a Plone deployment. `cdk8s-plone` does not run backups. It deploys the application; your data lives in PostgreSQL, so you protect the database. ## What to back up Plone stores its content in the ZODB, which this stack keeps in PostgreSQL through RelStorage. A backup of the PostgreSQL database is a backup of your site content. If your configuration keeps blobs on a separate volume rather than in the database, back up that volume as well. The application images and Kubernetes manifests are reproducible from your `cdk8s-plone` code, so they do not need a backup. ## Back up a CloudNativePG database CloudNativePG performs scheduled and on-demand backups to object storage through its own resources. Configure object-store backups on the `Cluster`, then schedule them with a `ScheduledBackup`: ```yaml apiVersion: postgresql.cnpg.io/v1 kind: ScheduledBackup metadata: name: plone-daily spec: schedule: "0 0 2 * * *" backupOwnerReference: self cluster: name: ``` Take an immediate backup with a `Backup` resource: ```yaml apiVersion: postgresql.cnpg.io/v1 kind: Backup metadata: name: plone-manual spec: cluster: name: ``` See the [CloudNativePG backup documentation](https://cloudnative-pg.io/documentation/current/backup/) for object-store credentials and retention policies. ## Back up a plain or standalone database For a database without an operator, take a logical dump with `pg_dump` from a client pod: ```shell kubectl exec -n -- \ pg_dump -U -d -Fc -f /tmp/plone.dump kubectl cp /:/tmp/plone.dump ./plone.dump ``` Run this on a schedule with a `CronJob`, and store the dump off-cluster. ## Restore For CloudNativePG, create a new `Cluster` with a `bootstrap.recovery` stanza that points at a backup, following the [CloudNativePG recovery guide](https://cloudnative-pg.io/documentation/current/recovery/). For a logical dump, restore into an empty database with `pg_restore`: ```shell kubectl cp ./plone.dump /:/tmp/plone.dump kubectl exec -n -- \ pg_restore -U -d --clean --if-exists /tmp/plone.dump ``` After the database is restored, restart the backend so it reconnects: ```shell kubectl rollout restart deployment/ -n ``` ```{warning} Restoring overwrites the current database. Take a fresh backup before you restore, so you can return to the current state if the restore goes wrong. ``` ## Verify Confirm a backup completed and is recent: ```shell kubectl get backup -n kubectl get scheduledbackup -n ``` After a restore, open the site and confirm your content is present. ## See also - {doc}`/how-to/upgrade-and-rollout` — back up before a risky upgrade. - {doc}`/explanation/architecture` — where Plone stores its data. - [CloudNativePG documentation](https://cloudnative-pg.io/documentation/current/) — backup, recovery, and retention.