backup-restore · diff
git:20260928.2939037 to git:20261014.1b8131c
3 added, 3 removed. Audit A to A.
---
name: backup-restore
description: >-
Manage kopiur Kopia-based backups and restores for Kubernetes PVs in this cluster.
user: "check backup status for app X" → describe the SnapshotPolicy/SnapshotSchedule
user: "restore from backup" → follow the restore workflow below
user: "trigger manual backup" → `kubectl kopiur snapshot now --policy <app> -n <ns> --wait`
user: "backup failing" → delegate to debug-cluster for mover pod logs
Use when the user mentions backups, restores, snapshots, SnapshotPolicy, SnapshotSchedule,
Restore, ClusterRepository, PVC recovery, or disaster recovery. This cluster uses kopiur
- (home-operations, kopia-native) — not VolSync, not restic. Migrated 2026-07-12.
+ (home-operations, kopia-native), not VolSync, not restic.
compatibility: Requires `kubectl` access to the cluster and the `kopiur` kubectl plugin; kopiur CRDs and the shared ClusterRepository secret must exist.
---
# Backup and restore (kopiur + Kopia)
## Quick reference
| Operation | Command |
|-----------|---------|
| List policies | `kubectl get snapshotpolicy -A` |
| List schedules | `kubectl get snapshotschedule -A` |
| List snapshots for an app | `kubectl kopiur snapshots list --policy <app> -n <ns>` |
| Trigger manual snapshot | `kubectl kopiur snapshot now --policy <app> -n <ns> --wait` |
| Check a restore | `kubectl get restore <app>-restore -n <ns>` |
| Status | `kubectl describe snapshotpolicy <app> -n <ns>` |
## Check status
A healthy policy shows `Ready: True` and a recent `status.lastSuccessfulSnapshot`. The
`SnapshotSchedule` object's `status.observedGeneration` sticking behind
`.metadata.generation` is a known cosmetic quirk (fleet-wide, harmless) — it makes the owning
Flux Kustomization's `wait: true` health check flap (`HealthCheckFailed ... status: 'InProgress'`,
self-clears on retry). Don't chase it; trust the policy's own `Ready` condition and a fresh
manual snapshot instead.
## Restore from backup
The procedure is [docs/kopiur-restore.md](../../../docs/kopiur-restore.md): suspend both
Kustomization and HelmRelease, pause KEDA, scale down every deployment sharing the PVC, delete
the PVC, resume, verify. That file is the single copy, and also covers point-in-time restore
- (`offset`/`asOf`/`snapshotRef`/`identity`), the kopiur#233 orphaned-`prime-*`-PVC trap and its
- sweep commands, and the live-uid check.
+ (`offset`/`asOf`/`snapshotRef`/`identity`), the `Completed`/`Ready: False` sweep, and the live-uid
+ check.
Not in that file: when the live uid does not match the manifest's `runAsUser`,
`KOPIUR_PUID`/`KOPIUR_PGID` (and, only for genuine root,
`KOPIUR_MOVER_CAPS_ADD: "[DAC_READ_SEARCH]"`) go in the app's own `ks.yaml`
`postBuild.substitute` block — see [references/restore-pvc.md](references/restore-pvc.md).
## Enable backups for a new app
Reference patterns in `kubernetes/components/kopiur/`. See
[references/restore-pvc.md](references/restore-pvc.md) for the full substitute-variable list.
## Troubleshooting (inline)
- Repository secret: `kubectl get secret -n kopiur-system kopia-nas-password` (shared across all apps
via credential projection — apps don't carry their own copy)
- `ClusterRepository` health: `kubectl get clusterrepository kopia-nas`
Symptom-keyed failures (PVC never claimed, restore stalling, wrong `dataSourceRef`, mover stuck
with no output) → [docs/kopiur-restore.md](../../../docs/kopiur-restore.md) Troubleshooting.
For mover logs and deep failures → [debug-cluster](../debug-cluster/SKILL.md).