Back up the database
Back up the Citrix SecurSpaces™ database before upgrades, migrations, and major configuration changes, and on a recurring schedule in production. If you use HashiCorp Vault for secrets, back up Vault on the same schedule.
On-premises and self-managed (internal Percona MongoDB)
Important:
Backups are disabled by default on the internal database. If you run it in production, enabling, scheduling, and restore-testing them is your responsibility. See The SecurSpaces database.
Use Percona Backup for MongoDB (PBM) as your primary, scheduled backup mechanism.
Use a manual mongodump only as a secondary, point-in-time snapshot before a specific
change.
Primary: Percona Backup for MongoDB (PBM)
PBM is the backup tool built into the Percona Operator. It supports on-demand and scheduled logical and physical backups and point-in-time recovery to an external object store (Amazon S3, Azure Blob Storage, Google Cloud Storage, or any S3-compatible store).
The chart with Percona Operator 1.23.0 ships PBM 2.15.0. Backups remain disabled by default.
Configure them in your Helm values with perconaServerMongoDB.backup, including enabled, storage,
schedules, retention, and point-in-time recovery (PITR). Configure the database Kubernetes service account
through perconaServerMongoDB.serviceAccount. The chart renders these settings into the Percona resources.
Keep backup settings in the values used for subsequent Helm upgrades. If you previously edited
spec.backup directly, carry those settings into perconaServerMongoDB.backup before applying the new
chart. Do not rely on custom-resource edits as the source of configuration for future upgrades.
For an existing deployment on operator 1.20.1, first complete the stepwise upgrade to 1.23.
Follow the Percona Operator backup documentation for the authoritative reference:
- Backups overview: https://docs.percona.com/percona-operator-for-mongodb/backups.html
- Configure storage: https://docs.percona.com/percona-operator-for-mongodb/backups-storage.html
- On-demand backups: https://docs.percona.com/percona-operator-for-mongodb/backups-ondemand.html
- Scheduled backups: https://docs.percona.com/percona-operator-for-mongodb/backups-scheduled.html
Example: enable PBM and back up to Amazon S3
This worked example follows the Percona Operator storage guide. Replace <release>
with your SecurSpaces Helm release name and <namespace> with your SecurSpaces namespace. Run
kubectl get psmdb -n <namespace> to confirm your cluster name — for SecurSpaces it is
<release>-psmdb-db.
1. Create a Secret with your S3 credentials. Save as backup-s3-secret.yaml
(the values are base64-encoded automatically when you use stringData):
apiVersion: v1
kind: Secret
metadata:
name: sds-backup-s3
type: Opaque
stringData:
AWS_ACCESS_KEY_ID: "<your-access-key-id>"
AWS_SECRET_ACCESS_KEY: "<your-secret-access-key>"
<!--NeedCopy-->
kubectl apply -f backup-s3-secret.yaml -n <namespace>
<!--NeedCopy-->
2. Enable backups and define the storage in your Helm values. Add the following to the values file used for your deployment. The storage entry references the Secret created above:
perconaServerMongoDB:
backup:
enabled: true
storages:
s3-primary:
type: s3
s3:
bucket: <your-backup-bucket>
region: <your-region> # for example, eu-central-1
prefix: sds/strong-network # optional sub-folder in the bucket
credentialsSecret: sds-backup-s3
<!--NeedCopy-->
Apply the values using your normal Helm upgrade command and the same chart version. For example:
helm upgrade <release> ./ninjahchart-<version>.tgz -n <namespace> -f <your-values.yaml>
<!--NeedCopy-->
Note On AWS EKS you can grant bucket access with an IAM role for the service account (IRSA) and omit
credentialsSecret. For Azure Blob or Google Cloud Storage, use theazureorgcsstorage type instead ofs3. For keyless GCS access, see GCS Workload Identity.
3. Take an on-demand backup. Create a PerconaServerMongoDBBackup resource that
references your cluster and storage. Save as sds-backup.yaml:
apiVersion: psmdb.percona.com/v1
kind: PerconaServerMongoDBBackup
metadata:
name: sds-backup-2026-07-02
namespace: <namespace>
spec:
clusterName: <release>-psmdb-db
storageName: s3-primary
type: logical # logical is the default; physical is also supported
<!--NeedCopy-->
kubectl apply -f sds-backup.yaml
<!--NeedCopy-->
4. Verify the backup completed. Track the backup resource until STATUS is
ready:
kubectl get psmdb-backup -n <namespace>
<!--NeedCopy-->
NAME CLUSTER STORAGE DESTINATION TYPE STATUS AGE
sds-backup-2026-07-02 <release>-psmdb-db s3-primary s3://<bucket>/sds/strong-network/… logical ready 2m
<!--NeedCopy-->
5. (Recommended) Add a schedule and point-in-time recovery. For ongoing
protection, add a backup task and enable PITR in the same perconaServerMongoDB.backup section of your
values file. Keep the storage definition from the previous step:
perconaServerMongoDB:
backup:
enabled: true
pitr:
enabled: true # continuous point-in-time recovery
tasks:
- name: daily-s3
enabled: true
schedule: "0 2 * * *" # every day at 02:00 (cron)
storageName: s3-primary
retention:
type: count
count: 7 # retain the 7 most recent scheduled backups
deleteFromStorage: true
<!--NeedCopy-->
Apply the updated values with your Helm upgrade command and confirm new backups appear on schedule. As a best practice, store backups in a different failure domain from the cluster — a separate cloud region or account — so that a cluster or region failure does not also destroy your backups.
Note Reapplying the same Helm values preserves the backup configuration. In GKE validation, a second Helm upgrade with unchanged values caused no restarts and backups continued.
GCS Workload Identity
Percona Operator 1.23.0 supports keyless backups to Google Cloud Storage (GCS) using Workload Identity
Federation for GKE. Use the native gcs storage type and omit gcs.credentialsSecret so PBM uses
Application Default Credentials. No service account JSON key or HMAC key is required.
Prepare GKE and bucket access
You need a GKE cluster with Workload Identity enabled, the GKE metadata server enabled on the node pools running the database and operator pods, a GCS backup bucket, and permission to manage that bucket’s IAM policy. See Google’s Workload Identity setup guide.
Use perconaServerMongoDB.serviceAccount in the chart values to configure the database service account.
Inspect the target chart for its service-account options before setting them:
helm show values ./ninjahchart-<version>.tgz
<!--NeedCopy-->
Grant bucket access to both Kubernetes service accounts: the one used by the database pods and the one used by the Percona operator. PBM needs access for backup and restore; the operator also needs access to delete expired backups from GCS. Discover the accounts from the running pods rather than assuming names:
kubectl get pods -n <namespace> \
-o custom-columns='POD:.metadata.name,SERVICE_ACCOUNT:.spec.serviceAccountName'
<!--NeedCopy-->
The following example grants bucket-level object access directly to the two Kubernetes service-account
principals. Replace the placeholders with the GKE cluster project’s ID and number, your namespace, bucket,
and the actual account names. roles/storage.objectUser allows object reads, writes, listing, and deletion.
PROJECT_ID="<gke-project-id>"
PROJECT_NUMBER="<gke-project-number>"
NAMESPACE="<namespace>"
GCS_BUCKET="<backup-bucket>"
DATABASE_KSA="<database-service-account>"
OPERATOR_KSA="<operator-service-account>"
POOL="projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog"
for KSA in "$DATABASE_KSA" "$OPERATOR_KSA"; do
gcloud storage buckets add-iam-policy-binding "gs://${GCS_BUCKET}" \
--member="principal://iam.googleapis.com/${POOL}/subject/ns/${NAMESPACE}/sa/${KSA}" \
--role="roles/storage.objectUser"
done
<!--NeedCopy-->
This direct-principal configuration does not require a Google service account key or service-account impersonation. If the operator runs in a different namespace, use that namespace in its IAM principal. If you change the database service account in Helm values, grant access to the new account as well.
Configure backups in Helm values
Merge this example into your deployment values alongside perconaServerMongoDB.serviceAccount.
It enables logical backups every 10 minutes, continuous PITR oplog capture, and retention of two scheduled
backups. Adjust the schedule and retention to your recovery requirements:
perconaServerMongoDB:
backup:
enabled: true
storages:
gcs-wi:
type: gcs
gcs:
bucket: <backup-bucket>
prefix: sds/mongodb
pitr:
enabled: true
tasks:
- name: gcs-every-10-minutes
enabled: true
schedule: "*/10 * * * *"
storageName: gcs-wi
type: logical
retention:
type: count
count: 2
deleteFromStorage: true
<!--NeedCopy-->
Apply the values with your normal Helm upgrade command after completing the Percona 1.23 upgrade.
If migrating from key-based GCS access, remove credentialsSecret from the storage’s gcs settings in
your values and verify it is absent from the resulting custom resource. A configured credentials Secret
takes precedence over Workload Identity.
Verify backups, retention, and restore
- Create the on-demand
PerconaServerMongoDBBackupshown in the S3 example above, using a unique name andstorageName: gcs-wi. Wait forreadyand confirm that the backup is present in the bucket. - Confirm scheduled backups complete and continuous oplog chunks appear for PITR. PITR requires a completed base backup and oplog coverage for the chosen recovery time.
- Confirm retention deletes expired backups from both Kubernetes and GCS. If objects remain in GCS, check bucket permissions for the operator’s service account as well as the database account.
- Keep the same backup values for subsequent Helm upgrades and verify backups continue afterward.
- Test restoring into a replacement deployment, including a restore to a chosen second when using PITR. See Restore the database.
This flow was validated on GKE with direct bucket grants to both Kubernetes service accounts, on-demand
and scheduled backups, PITR, retention count 2, and a repeated Helm upgrade. Recovery was also validated
after deleting the deployment and volumes, reinstalling, and restoring to a chosen second; the recovered
data matched and the platform was operational.
For authentication and storage details, see Percona’s GCS backup guide.
Secondary: logical snapshot with mongodump
The Percona upgrade kit
takes a mongodump archive automatically before changing versions and includes matching restore and
delete scripts. Keep this pre-upgrade archive until platform validation is complete. It is separate from
your scheduled PBM backups and PITR storage.
mongodump / mongorestore are the official MongoDB database tools, and SecurSpaces uses
them in its own replica-set migration procedure, so this is a supported method — not
a workaround.
It is safe for ad hoc, quiesced snapshots (for example, immediately before an upgrade) when you follow these rules:
-
Quiesce writes before you dump, or dump from a secondary member.
mongodumpis only guaranteed consistent across collections when the database is not being written to. The simplest way to get a clean snapshot is to scale the SecurSpaces services to0first (the same quiesce step used in the restore procedure), then dump.mongodumpcannot produce a cross-collection point-in-time snapshot of a single database on a live system — for online, point-in-time backups, use PBM instead. - Store the archive off-cluster and protect it (it contains encrypted secrets unless you use Vault).
-
Restore only into a quiesced platform (see the restore section), and never use
destructive flags such as
--dropagainst a live, in-use database.
It is not a replacement for scheduled, point-in-time disaster recovery — PBM
(internal) or your managed service’s backups remain the primary strategy. Use
mongodump to capture a known-good snapshot before a risky change.
# Identify the Percona pods
kubectl get psmdb
kubectl get pods -l app.kubernetes.io/name=percona-server-mongodb
# Confirm which pod is primary (look for "[direct: primary]" in the prompt)
kubectl exec -it <pod>-rs0-0 -- mongosh \
--authenticationDatabase admin --username <admin-user> --password <admin-password>
# Dump the strong-network database from the primary (quiesce writes first)
kubectl exec -it <primary-pod> -- mongodump \
--db strong-network \
--username <admin-user> --password <admin-password> \
--authenticationDatabase admin \
--gzip --archive=/tmp/strong-network-backup.gz
# Copy the archive off the pod
kubectl cp <primary-pod>:/tmp/strong-network-backup.gz strong-network-backup.gz
<!--NeedCopy-->
For tool reference, see the MongoDB documentation for mongodump:
https://www.mongodb.com/docs/database-tools/mongodump/
Hosted MongoDB services
When you use a managed MongoDB service, the provider supplies the backup tooling. Enable and configure it according to your recovery objectives (RPO/RTO).
SecurSpaces supports hosted MongoDB services on all three major hyperscalers (AWS, Azure, and Google Cloud). MongoDB Atlas is available on all three and is the option the SecurSpaces deployment guides reference. Use Atlas Cloud Backups with continuous (point-in-time) backup enabled:
- Atlas Cloud Backups overview: https://www.mongodb.com/docs/atlas/backup/cloud-backup/overview/
- Atlas restore overview: https://www.mongodb.com/docs/atlas/backup/cloud-backup/restore-overview/
If you use a cloud-native, MongoDB-compatible service instead of Atlas, enable its backup feature using the provider documentation below.
| Platform | Service | Official backup documentation |
|---|---|---|
| AWS | Amazon DocumentDB, or MongoDB Atlas on AWS | Backing up and restoring in Amazon DocumentDB · Atlas Cloud Backups |
| Azure | Azure Cosmos DB for MongoDB, or MongoDB Atlas on Azure | Online backup and on-demand restore (Cosmos DB) · Reliability in Azure Cosmos DB for MongoDB (vCore) |
| GCP | MongoDB Atlas on Google Cloud | Atlas Cloud Backups. Google Cloud has no first-party managed MongoDB. |
General guidance for hosted services:
- Turn on continuous / point-in-time backup, not just daily snapshots, to minimize data loss.
- Set a retention period that meets your compliance and recovery requirements.
- Periodically test restoring a snapshot into a non-production cluster.