Backups
Creating, configuring and controlling backup definitions.
View as MarkdownA backup is a definition. These commands create and shape it; the schedule runs it.
For anything more than one backup, prefer sctl apply with a manifest.
These commands are the imperative equivalent, and are what apply calls underneath.
Listing
sctl backup listNAME ID KIND SOURCE STATE SCHEDULE
prod-db 018f3c2a-9e11-7c4d-b0a1-2e6f5d3c9a70 local postgres active 0 2 * * *
uploads 018f4d1b-... cloud s3 paused 0 4 * * *This is where you get the IDs everything else needs.
BACKUP_ID=$(sctl backup list | awk '$1 == "prod-db" { print $2 }')Creating
sctl backup create prod-db --kind local--kind is required and is one of local, cloud or manual.
Kind is immutable. It decides who holds your source credentials, so changing it would
silently move a credential across a trust boundary. sctl backup configure has no --kind
flag for that reason. To change it, create a second backup.
A new backup is a draft. It holds no schedule and produces nothing until it is complete.
Configuring
sctl backup configure "$BACKUP_ID" \
--source-type postgres \
--worker <worker-id> \
--schedule "0 2 * * *" \
--keep-last 10 \
--expire-after 90dOmitted flags are left alone. The update is a merge, so you can configure one field without restating the rest. The backend activates the backup itself as soon as the definition is complete.
| Flag | Applies to | Notes |
|---|---|---|
--name | All | Rename |
--source-type | local, cloud | Must be legal for the kind |
--worker | local | Worker ID, required before it can activate |
--schedule | local, cloud | Cron, evaluated in UTC |
--source key=value | cloud only | Repeatable. Non-secret source facts |
--credential key=value | cloud only | Repeatable. Secrets, routed to our vault |
--encryption-key <path> | All | Path to an armoured public key file |
--compression | All | Enable gzip |
--compression-level | All | 1 to 9, or 0 for the default |
--keep-last | All | Retention floor |
--expire-after | All | Retention age limit, e.g. 90d |
--lock-for | All | Protection window, e.g. 30d |
Cloud sources
sctl backup configure "$BACKUP_ID" \
--source-type postgres \
--source host=db.example.com --source port=5432 --source database=app \
--credential password="$PGPASSWORD" \
--schedule "0 2 * * *"--source carries facts we store and return; --credential carries secrets we store in the
vault and never return. Sending a secret in the wrong one is corrected for you: the split is
judged by the source type, not by which flag you used.
A local backup takes neither. Its credentials live in the worker's own config.yaml and
never reach us, so --source and --credential are refused on one.
Retention is write-once
sctl backup configure "$BACKUP_ID" --keep-last 10 --expire-after 90d --lock-for 30dRetention can be set once. Changing it afterwards is refused with 409 retention_immutable, including loosening it. Re-sending the identical policy is accepted.
Decide it before the first run, or create a new backup.
--lock-for may never exceed --expire-after: a policy cannot forbid a deletion it also
requires.
Running one now
sctl backup trigger "$BACKUP_ID"
sctl run list --backup "$BACKUP_ID"A triggered run is ordinary in every respect: same pipeline, same artifact, same retention, same billing. It does not shift the schedule.
A trigger always runs, even when a scheduled run is already in flight. Scheduled fires skip when one is running; manual triggers do not.
Pausing
sctl backup pause "$BACKUP_ID"
sctl backup resume "$BACKUP_ID"Pausing suspends the schedule and leaves the definition and its artifacts alone. Runs are not queued while paused: resuming starts from the next scheduled fire.
A manual backup has no schedule and cannot be paused.
Submitting to a manual backup
sctl backup submit "$BACKUP_ID" ./quarterly-export.tar.gzSubmitted ./quarterly-export.tar.gz as run manual-018f3c2a-.... post-backup is running.One command does the whole flow: create the run, request an upload target, upload directly to storage, and confirm. The bytes never pass through our API.
Deleting
sctl backup delete "$BACKUP_ID"Refused while the backup still has artifacts. A definition cannot be removed out from under the things it produced. Delete or expire the artifacts first, and note that a locked artifact blocks this until its lock lapses.
Pause is almost always what you want instead.