restverify
Rehearse and verify restic restores locally, on a schedule, with a diff-proof report.
Status: v0.1.0 — first release.
run,reportandcronare implemented and verified against real repos;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
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.
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.
Metadata
Release files for restverify 0.1.0
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.1.0.tar.gz | 109.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| restverify-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 155.0 kB
Release files / restverify-0.1.0.tar.gz
| Download URL | restverify-0.1.0.tar.gz |
|---|---|
| Size | 109.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a54b7dc3c2aff8ea9e7f5be1d3f61192784593a5fc11ed2da874d9a1502ab98
|
|
BLAKE2b-256 checksum How to use checksums |
26181fab25c699f8146f127395289ed04de296c1620f364238e5f8b829079dcc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / restverify-0.1.0-py3-none-any.whl
| Download URL | restverify-0.1.0-py3-none-any.whl |
|---|---|
| Size | 45.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5ae999e4bf6ffee59e3bfc67fc1a2727f510555723466f6787421a2346c3066e
|
|
BLAKE2b-256 checksum How to use checksums |
d55b8260009e7cb0398c58695f6592e61c3cb88c818105541457e30c3f364f7a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|