Backup & Restore
KubeClaw can back up the Gateway state directory to any S3-compatible storage (AWS S3, MinIO, Backblaze B2, Cloudflare R2) on a cron schedule. A pre-delete hook also runs a final backup before helm uninstall, so state is preserved even when tearing down the release.
Backups use rclone to copy the flat Markdown files. No database dump or special tooling is needed.
What gets backed up
- Primary PVC:
/home/node/.openclaw(excluding workspace if split) - Workspace PVC:
/home/node/.openclaw/workspace(if split volumes are enabled)
Enable S3 backups
Add S3 credentials to secret.data and enable the backup:
secret:
create: true
data:
OPENCLAW_GATEWAY_TOKEN: "your-token"
S3_ENDPOINT: "https://s3.us-east-1.amazonaws.com"
S3_BUCKET: "my-kubeclaw-backups"
S3_ACCESS_KEY_ID: "AKIAEXAMPLE"
S3_SECRET_ACCESS_KEY: "your-secret-key"
S3_REGION: "us-east-1"
backup:
enabled: true
schedule: "0 2 * * *" # daily at 2am UTC
The chart validates that S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY are present in secret.data when backup.enabled is true.
S3 path layout
Scheduled backups are timestamped. The pre-delete backup overwrites a single pre-delete/ prefix so only the latest snapshot is kept:
s3://my-kubeclaw-backups/
<namespace>/<release>/
2026-03-07T02-00-00Z/ # scheduled
2026-03-08T02-00-00Z/ # scheduled
pre-delete/ # latest pre-delete snapshot
Override the <namespace>/<release> prefix with backup.pathPrefix.
Non-AWS providers
Any S3-compatible endpoint works. Set S3_ENDPOINT to your provider's URL:
| Provider | S3_ENDPOINT example |
|---|---|
| MinIO | http://minio.minio.svc:9000 |
| Backblaze B2 | https://s3.us-west-004.backblazeb2.com |
| Cloudflare R2 | https://<account-id>.r2.cloudflarestorage.com |
Disable the pre-delete hook
If you do not want a backup on helm uninstall:
backup:
enabled: true
onDelete:
enabled: false
Restore methods
Three restore methods are supported depending on your backup strategy.
Method 1: CSI VolumeSnapshot
Requires a CSI snapshot controller, VolumeSnapshot and VolumeSnapshotClass CRDs, and an existing snapshot.
Identify the snapshot:
kubectl -n <namespace> get volumesnapshots
Scale down the Gateway:
kubectl -n <namespace> scale statefulset/openclaw-gateway --replicas=0
Delete the existing PVC (verify the snapshot is READYTOUSE: true first):
kubectl -n <namespace> delete pvc state-openclaw-gateway-0
Create a new PVC from the snapshot:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: state-openclaw-gateway-0
namespace: <namespace>
spec:
accessModes:
- ReadWriteOnce
storageClassName: <your-storage-class>
resources:
requests:
storage: <size-matching-original>
dataSource:
name: <snapshot-name>
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
Scale the Gateway back up:
kubectl -n <namespace> scale statefulset/openclaw-gateway --replicas=1
Method 2: Manual tarball
Create a backup from the running Gateway:
kubectl -n <namespace> exec statefulset/<release-name> -- \
tar czf - /home/node/.openclaw \
> ./openclaw-backup/openclaw-state-$(date +%Y%m%d%H%M%S).tar.gz
Restore by scaling down the Gateway, running a temporary busybox pod with the PVC mounted, copying the tarball in, extracting, then scaling back up. See the full restore runbook for step-by-step instructions.
Method 3: Restore from S3
If the chart's S3 backup feature (backup.enabled: true) is configured, use rclone to pull the backup into the PVC.
List available backups:
rclone lsd s3:<bucket>/<namespace>/<release>/
Restore by scaling down the Gateway, running a temporary rclone pod with the PVC mounted, pulling the backup with rclone copy, then scaling back up. See the full restore runbook for detailed commands.
Post-restore checklist
- Gateway pods are Running and Ready (readiness probe passes)
openclaw doctorreports no critical issuesopenclaw statusshows expected gateway state- Control UI is accessible and authenticated
- No unexpected PVC size changes (
kubectl get pvc)
Troubleshooting
Gateway fails to start after restore: run doctor to repair config issues.
kubectl -n <namespace> exec statefulset/<release-name> -- \
node dist/index.js doctor --yes
Config is invalid after restore: delete the config file and let the Gateway regenerate defaults.
kubectl -n <namespace> exec statefulset/<release-name> -- \
rm /home/node/.openclaw/openclaw.json
kubectl -n <namespace> rollout restart statefulset/<release-name>