You are viewing documentation for Cozystack next, which is currently in beta. For the latest stable version, see the v1.4 documentation.
Application Backup and Recovery
This guide covers backing up and restoring Cozystack-managed databases — Postgres, MariaDB, and ClickHouse — as a tenant user: running one-off and scheduled backups, checking status, and restoring from a backup either in place or into a separate target instance.
Storage, credentials, and the BackupClass are admin-provisioned. Before you can run a BackupJob, an administrator provisions the S3 storage and the per-application credential Secrets your driver expects, and creates the cluster-scoped BackupClass you reference. Ask your administrator for:
- the
BackupClassname to use for your application Kind (you cannot listBackupClassresources under your tenant kubeconfig — they are cluster-scoped); - confirmation that the per-application credential Secrets exist in your namespace for every managed-DB application you want to back up.
Admins follow the Managed Application Backup Configuration guide.
These backups are data-only. Each strategy snapshots the database contents through the operator’s native mechanism (CloudNativePG barman, mariadb-operator dumps, Altinity clickhouse-backup). They do not capture the apps.cozystack.io/* CR, its HelmRelease, chart values, or operator-managed Secrets.
To restore you must either:
- keep the source application alive and restore in place (each driver re-bootstraps data into the existing operator-managed cluster), or
- pre-provision an empty target application of the same Kind, then restore into it.
For backups that include the application’s Helm release, CRs, and PVC snapshots (used for VMInstance / VMDisk), see Backup and Recovery (VMs).
Prerequisites
- A
BackupClassname handed to you by your administrator (for example,postgres-data-backupfor aPostgresapplication). - An existing managed-DB application (
Postgres,MariaDB, orClickHouse) in your tenant namespace. kubectland a tenant kubeconfig with thetenant-<ns>-adminrole.
The examples below assume tenant-user for the tenant namespace; substitute your own.
Run a backup
One-off backup
Use a BackupJob for an ad-hoc backup (for example, before a risky change):
apiVersion: backups.cozystack.io/v1alpha1
kind: BackupJob
metadata:
name: my-postgres-adhoc
namespace: tenant-user
spec:
applicationRef:
apiGroup: apps.cozystack.io
kind: Postgres
name: my-postgres
backupClassName: postgres-data-backup
kubectl apply -f backupjob.yaml
kubectl -n tenant-user get backupjobs
kubectl -n tenant-user describe backupjob my-postgres-adhoc
When the BackupJob reaches phase: Succeeded, the driver creates a Backup object with the same name. That name is what you reference when restoring.
Replace Postgres / postgres-data-backup with MariaDB / mariadb-data-backup or ClickHouse / clickhouse-data-backup for the other drivers.
Scheduled backup
Use a Plan for cron-driven recurring backups:
apiVersion: backups.cozystack.io/v1alpha1
kind: Plan
metadata:
name: my-postgres-daily
namespace: tenant-user
spec:
applicationRef:
apiGroup: apps.cozystack.io
kind: Postgres
name: my-postgres
backupClassName: postgres-data-backup
schedule:
type: cron
cron: "0 */6 * * *" # every 6 hours
Each scheduled run creates a BackupJob (and, on success, a Backup) named after the Plan with a timestamp suffix.
kubectl apply -f plan.yaml
kubectl -n tenant-user get plans
kubectl -n tenant-user get backupjobs -l backups.cozystack.io/plan=my-postgres-daily
Check backup status
List BackupJob and Backup resources in the namespace:
kubectl -n tenant-user get backupjobs
kubectl -n tenant-user get backups
Inspect a failed run:
kubectl -n tenant-user get backupjob my-postgres-adhoc -o jsonpath='{.status.message}'
kubectl -n tenant-user describe backupjob my-postgres-adhoc
kubectl -n tenant-user get events --field-selector involvedObject.name=my-postgres-adhoc
If status.message does not pinpoint the failure, hand the BackupJob name to your administrator and they will inspect the operator-native CR the driver created (see
Tenant escalation: driver-side diagnostics in the admin guide).
Restore in place
An in-place restore replays the backup into the same application. Use this to roll back accidental deletion or corruption on a live database you intend to keep using under the same name.
apiVersion: backups.cozystack.io/v1alpha1
kind: RestoreJob
metadata:
name: my-postgres-restore-inplace
namespace: tenant-user
spec:
backupRef:
name: my-postgres-adhoc
# targetApplicationRef omitted: driver restores into Backup.spec.applicationRef.
# options:
# recoveryTime: "2026-05-01T12:00:00Z" # Postgres only; RFC3339 PITR
kubectl apply -f restorejob.yaml
kubectl -n tenant-user get restorejobs
kubectl -n tenant-user describe restorejob my-postgres-restore-inplace
Per-driver caveats
- Postgres (CNPG) — the driver deletes the live
cnpg.io/Clusterand its PVCs, then re-bootstraps from the Barman archive. Connections drop for the duration.spec.options.recoveryTime(RFC3339) is supported for point-in-time recovery; omit it to restore to the latest WAL. - MariaDB — the operator replays the logical dump into the live
MariaDBviamariadb-import. Pre-existing tables will collide; pre-truncate the relevant schemas if your dump does not includeDROP TABLE. - ClickHouse — the Altinity strategy does not pass
clickhouse-backup --rm. You are responsible for dropping conflicting tables on the source before submitting theRestoreJob; otherwise the operation fails with a duplicate-table error.
Restore to a copy
A to-copy restore replays the backup into a different, freshly-provisioned application of the same Kind. Use this for disaster-recovery drills, side-by-side validation, branch databases, or migrating to a new version of the upstream operator.
First, provision an empty target application with the same Kind. For example, an empty Postgres:
apiVersion: apps.cozystack.io/v1alpha1
kind: Postgres
metadata:
name: my-postgres-restored
namespace: tenant-user
spec:
# ...same shape as the source, no bootstrap data required...
Wait for the target to become Ready, then submit a RestoreJob that points at it:
apiVersion: backups.cozystack.io/v1alpha1
kind: RestoreJob
metadata:
name: my-postgres-restore-to-copy
namespace: tenant-user
spec:
backupRef:
name: my-postgres-adhoc
targetApplicationRef:
apiGroup: apps.cozystack.io
kind: Postgres
name: my-postgres-restored
The source application stays untouched. Cross-namespace restores are not supported — targetApplicationRef is a local reference; the target must live in the same namespace as the RestoreJob.
Limitations and lifecycle
- Data-only scope. Application CRs, HelmReleases, chart values, and operator-managed Secrets (e.g.
cnpg.iosuperuser secret,clickhouse-installationusers) are not captured. Pre-provision the target application before a to-copy restore. - Archive retention is driver-owned. Deleting a Cozystack
BackupCR removes the artefact reference but leaves the actual S3 object intact. Each driver enforces its own retention:- CNPG:
retentionPolicyon the strategy (admin-owned; default30din the admin example). - MariaDB:
cleanupStrategyon the operator-sideBackupCR or rotation at the bucket level (admin-owned). - ClickHouse: governed by the in-pod sidecar’s retention configuration. To purge an archive ahead of schedule, ask your administrator — the call goes against the
clickhouse-backupHTTP API on the sidecar.
- CNPG:
- ClickHouse depends on the in-chart sidecar. The Altinity strategy is a thin HTTP client; the backup itself runs inside each
chi-*Pod viaclickhouse-backup. Disablingbackup.enabledon the application also disables the BackupClass flow.
Troubleshooting
If a BackupJob or RestoreJob ends in phase: Failed, start with what you can see in your namespace:
kubectl -n tenant-user get backupjob my-postgres-adhoc -o jsonpath='{.status.message}'
kubectl -n tenant-user get restorejob my-postgres-restore-inplace -o jsonpath='{.status.message}'
kubectl -n tenant-user describe backupjob my-postgres-adhoc
kubectl -n tenant-user get events --field-selector involvedObject.name=my-postgres-adhoc
If those do not explain the failure, the next layer of diagnostics lives on the operator-native CR the driver created (cnpg.io/Backup, k8s.mariadb.com/Backup, or the ClickHouse strategy Pod logs). These resources are not reachable under the tenant kubeconfig — hand the BackupJob name to your administrator and they will follow
Tenant escalation: driver-side diagnostics.
See also
- Managed Application Backup Configuration — how administrators define strategies and
BackupClassresources. - Backup and Recovery (VMs) — the parallel guide for VMInstance / VMDisk backups (HelmRelease + CRs + PVC snapshots).
- Velero Backup Configuration — administrator setup for the Velero-driven VM backups.