Skip to main content

restverify

Rehearse and verify restic restores locally, on a schedule, with a diff-proof report.

Status: v0.2.1 — signed releases, CI drill, sandboxed restores. run, report and cron are implemented and verified against real repos; the release train is signed (tag + artefacts); a 1.02 GiB / 1253-file drill over an SFTP backend, run as a non-root user, passed with 0 diffs (docs/I9-DRILL.md); the drill ships as a GitHub Action (docs/I10-CI.md); and run --sandbox restores inside a purged container (docs/I11-SANDBOX.md). init --json is still deferred. Verify with a repo you can afford to rehearse on.

Why

restic check validates the repository's internal structure. It does not prove the repository can be restored. The restic project tracks this as open issue #2332 ("Backups are only real if they're able to be restored"). Today everyone hand-rolls a restore && diff script that decays silently.

restverify is the verification layer: it restores to a temp directory, compares against the source, records the run, and exits with a code your cron/CI can act on. It does not orchestrate backups.

Install

python3 -m pip install restverify     # or: pipx install restverify

Requires Python 3.11+ and a restic binary on PATH.

First run

restverify run -r /srv/backup

The run line keeps the Phase-2 field order — ✓ restored snapshot <id>: N files / X in Ys; N diffs — rather than the PDF's example order; three increments of regression tests pin this order and the rewrite was cosmetic (I5 ruling R1).

Scheduled verification

restverify cron -r /srv/backup            # one ready-to-paste crontab line
restverify cron -r /srv/backup --systemd  # a .service + .timer pair instead

cron prints and never installs: no crontab is modified, systemctl is never called, and nothing is written into any unit directory. It prints one example cadence and leaves the schedule to you. A scheduler runs with a minimal environment, so set RESTIC_PASSWORD_COMMAND (or RESTIC_PASSWORD_FILE) there — restverify never stores your password.

Sandboxed verification (optional isolation)

restverify run -r /srv/backup --sandbox

The restore runs inside a disposable container (your restic binary, your temp dir, your uid — no image builds, nothing persists) and is purged on every exit, including a kill -9 mid-restore: the next run sweeps any leftover container automatically. Local repos mount read-only with no network; the verification, history and exit codes are identical to a native run. Requires docker (or a compatible runtime) on PATH with socket access for your user — never sudo. See docs/I11-SANDBOX.md for the measured gate.

CI: the nightly restore-drill

A scheduled GitHub Action that drills your backup ships in this repository (templates/ci-drill/, R44): it installs restic, downloads and GPG-verifies the released restverify wheel, restores and verifies a fixture (exit 0), then proves the drill still bites by tampering one byte (exit 2). Copy the workflow into your repository, point it at your restic repo via secrets, and a degraded backup turns the nightly job red before you ever need it for real. The same drill runs outside GitHub as a plain script (templates/ci-drill/scripts/drill.sh). Transcript and proof: docs/I10-CI.md.

History

Every verification writes one row to a local SQLite store — failures included, because a trend that hides failures is worse than no trend:

  • store: ~/.local/state/restverify/history.db (XDG state dir; override with RESTVERIFY_STATE=/some/dir)
  • retention: the newest 1000 rows per repository, pruned on write; the first prune announces itself on stderr
  • read it with restverify report (human) or restverify report --json (a "schema": 1 envelope)
  • --dry-run writes nothing; disabling the store is not supported yet

Honest limits (required by the contract)

  • Biggest risk: operators who already run a full orchestrator (resticprofile, restickler) will not switch. Mitigation: restverify is verification-only — bring your own orchestration — and it offers an exit-code contract nothing else provides.
  • Verification is as good as the comparison you ask for: without a source path it only proves the restore completed, not that the data matches.
  • Not a backup tool. No cloud targets, no prune/forget, no dashboards, no bouncer.

Release files for restverify 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for restverify 0.2.1
File Size Uploaded
restverify-0.2.1.tar.gz 153.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for restverify 0.2.1
File Interpreter ABI Platform
restverify-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 207.2 kB

Release files / restverify-0.2.1.tar.gz

Download URL restverify-0.2.1.tar.gz
Size 153.5 kB
Tags Source
SHA-256 checksum
How to use checksums
818e19e4d1dc519574bcf8d5b4ff4158b7d21f098962f3a7428da935517b21ed
BLAKE2b-256 checksum
How to use checksums
ee7e5de208f1923a8d6a4bedb5301360e3aa22e5d7f35ea03af80c2b88d5b45a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / restverify-0.2.1-py3-none-any.whl

Download URL restverify-0.2.1-py3-none-any.whl
Size 53.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28369b6f40ac226687b3241bef620879a98326b7e43a45ab489ddbea7e78bfe2
BLAKE2b-256 checksum
How to use checksums
622705e974edd1eaa3193a46eebc8c4f0100f821ddafd93544a72508d53a3813
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page