Webhook icon
Schedule icon
Commands icon
Docker icon
Script icon
If icon
SlackIncomingWebhook icon
Pause icon
Loop icon
Log icon
Fail icon
Set icon

Kopia Snapshot Shrink Retention Pin Guard

Detect Kopia snapshots that suddenly shrank, pin the last good ones after approval so retention keeps them, and verify the pins in the repository.

Categories
Infrastructure

Kopia backs up whatever the source path contains, so an unmounted volume or wiped directory produces a perfectly "successful" empty snapshot. Retention then counts it as the newest snapshot, and every empty snapshot pushes a good one closer to expiry. This blueprint learns what normal looks like per source, catches the shrink, and pins the last good snapshots before retention removes them.

How it works

  1. A webhook (called after kopia snapshot create) or a six-hourly schedule starts the flow; concurrency keeps one plan at a time.
  2. list_snapshots connects read-only and runs kopia snapshot list --json, with --all, which returns the manifests of every user, host and source (without it Kopia lists only the current user and host).
  3. analyze_snapshots reads the previous baseline from Kestra KV, then classifies each new snapshot by stats.fileCount, stats.totalSize and stats.errorCount against the median of the last healthy snapshots. Anomalies never enter the baseline, so a run of empty backups cannot redefine normal.
  4. For an anomalous source it plans kopia snapshot pin on the newest known-good snapshots still in the repository; for a recovered source it plans the unpin.
  5. pause_for_approval holds the plan for 12 hours; an operator resumes it and decides whether pins may be released.
  6. apply_plan loops over the planned operations, relist_snapshots re-reads the repository and verify_plan fails the run unless every pin is really there and no pinned snapshot vanished.
  7. The audit entry and the new baseline are written to KV, and Slack gets the verified result.

What you get

  • Per-source baselines that survive retention deleting the healthy snapshots they were learned from.
  • A write path that uses Kopia's own pin mechanism, which retention never expires.
  • Approval before any repository change, and a measured result afterwards.

Who it's for

  • Platform and SRE teams running Kopia on S3-compatible storage.
  • Anyone who has restored from a backup and found it empty.

Why orchestrate this with Kestra

The decision needs memory across runs, a human in the middle and a verification pass; a cron script has none of them. KV holds the baselines, Pause holds the plan, and Loop applies it per source with audit trail.

Prerequisites

  • A Kopia repository on S3-compatible storage, Docker on the worker, and a Slack webhook.

Secrets

  • KOPIA_PASSWORD: repository password.
  • KOPIA_S3_ACCESS_KEY and KOPIA_S3_SECRET_KEY: storage credentials with read and write access to the repository.
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook.
  • KOPIA_GUARD_WEBHOOK_KEY: key protecting the webhook trigger.

Quick start

  1. Create the five secrets and start a test MinIO with a bucket; create a repository with kopia repository create s3 and take a few snapshots of a sample directory. For a plain-HTTP MinIO set s3_disable_tls to true.
  2. Execute the flow once with your s3_endpoint, s3_bucket and s3_prefix to learn the baseline, then enable the six-hourly trigger.
  3. Empty the sample directory, take another snapshot and execute again: the flow alerts and pauses.
  4. Resume it, then check kopia snapshot list for the kestra-retention-guard pin.

How to extend

  • Gate your own kopia snapshot expire --delete job on this guard's state.
  • Add a Kopia snapshot verify step for the pinned snapshots.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.