Skip to content

Repository files navigation

RestoreLab

CI License: MIT Go Version

Recovery drill verification for PostgreSQL backups.

RestoreLab demo

RestoreLab answers one question:

Can I actually restore this archive right now, in isolation, without touching production?

It is not a backup tool. It is a verification layer on top of Restic that restores a PostgreSQL archive inside a hardened, disposable Docker container, runs your SQL checks against it, and prints a report showing exactly what was and was not tested.

Why this exists

A backup job reporting "success" only proves the job ran. It does not prove the archive is restorable, and it does not prove the database that comes out of it is structurally correct. The gap between "the backup script exited 0" and "I can actually recover this service" is where real incidents happen — and it usually only gets discovered during an actual outage, when it's too late to do anything but apologize.

RestoreLab closes that gap by giving you a way to prove restorability on a schedule, in an isolated sandbox, without ever touching your production database or host.

How it works

flowchart LR
    A[("Restic\nrepository")] -->|restore snapshot| B["PostgreSQL\ncustom-format dump"]
    B --> C

    subgraph C["Hardened disposable Docker sandbox"]
        direction LR
        D["pg_restore"] --> E["SQL checks\n(your contract)"]
    end

    E --> F["JSON + HTML\nreport"]
    C -.->|always, via defer| G["Cleanup\n(container + volumes removed)"]

    style C fill:#0d1117,stroke:#58a6ff,color:#c9d1d9
    style G fill:#161b22,stroke:#8b949e,color:#8b949e
Loading

The sandbox has no published ports, no Docker socket mount, and never touches your production database. See Security properties for the full list of hardening measures.

Why not just...

Approach Archive exists Archive not corrupted Database actually restores Runs isolated from production
Backup job reported success Yes No No
restic check Yes Yes No
pg_restore --list Yes Yes No
Manual restore drill by hand Yes Yes Yes Usually not (spare or prod-adjacent box)
RestoreLab Yes Yes Yes Yes — hardened, disposable container

Scope of v0.1.0

Supported: Restic repositories / PostgreSQL (custom-format dumps) / Docker Engine / CLI with JSON + HTML reports.

Not supported in v0.1.0: Borg, PBS, Duplicati / MySQL, MariaDB, SQLite / Kubernetes, Podman / Web UI, scheduler, alerts.

Anything not in the supported list is deliberately deferred to ROADMAP.md and will not enter v0.1.0.

Quick start

Install directly (requires Go 1.22+):

go install github.com/techdev-lab/restorelab/cmd/restorelab@latest

Or build from source:

git clone https://github.com/techdev-lab/restorelab
cd restorelab
go build -o restorelab ./cmd/restorelab

On Debian/Ubuntu, the Docker SDK requires CGO. See docs/BUILD_REQUIREMENTS.md.

Validate a contract:

export RESTIC_REPOSITORY=/path/to/restic-repo
export RESTIC_PASSWORD_FILE=/path/to/password-file
export TEST_DB_PASSWORD=your-sandbox-db-password

./restorelab validate examples/real-world/immich-real-test.yaml

Run a drill:

./restorelab run examples/real-world/immich-real-test.yaml \
  --json=report.json --html=report.html

Prerequisites

  • Docker Engine 26.0.0+ (fixes CVE-2024-29018)
  • Restic 0.14.0+ (0.17.0+ recommended for size metadata)
  • Go 1.22+ if building from source
  • PostgreSQL image pinned by digest

Real-world validation

See docs/REAL-WORLD-VALIDATION.md for findings from running RestoreLab against production backup archives, including a case where it surfaced that a service's data directory contained no persistent database at all — a gap that would only have been discovered during an actual recovery attempt.

Security properties

  • cap_drop: ALL
  • no-new-privileges
  • Read-only root filesystem
  • No published ports
  • No privileged mode
  • No Docker socket mount
  • Internal network only
  • Artifact bind-mounted read-only
  • Memory / PIDs / shm bounded
  • Cleanup via defer, guaranteed on success, failure, or interrupt

See SECURITY.md for the full threat model.

Exit codes

0  success (overall PASS or WARNING)
1  failure (contract invalid, drill failed, runtime error)
2  usage error

Roadmap

  • v0.2.0: MariaDB support
  • v0.3.0: Borg provider
  • v0.4.0: Proxmox Backup Server
  • v1.0.0: Optional web UI, scheduling, alerts

See ROADMAP.md for details.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for guidelines.

License

MIT. See LICENSE.

About

Zero-trust PostgreSQL recovery drill for Restic backups, verified inside a hardened Docker sandbox.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages