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,reportandcronare 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); andrun --sandboxrestores inside a purged container (docs/I11-SANDBOX.md).init --jsonis 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 withRESTVERIFY_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) orrestverify report --json(a"schema": 1envelope) --dry-runwrites 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)
| File | Size | Uploaded | |
|---|---|---|---|
| restverify-0.2.1.tar.gz | 153.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|