Point-in-Time Restore
Recover files from any restic snapshot — selective file restore, full bucket restore, disaster recovery, and RTO targets.
RESTIC_REPOSITORY, RESTIC_PASSWORD, and B2 credentials are available in the backup container. Run restic snapshots first to confirm the snapshot you need exists.
On This Page
Snapshot Model
restic takes a snapshot of the MinIO data volume (/data) once per day. Each snapshot is a point-in-time view of the entire MinIO data directory including all buckets, all tenants, and all object metadata. Snapshots are stored encrypted in Backblaze B2 as deduplicated blocks — only changed blocks are stored per backup.
| Snapshot Age | Availability | Policy |
|---|---|---|
| 0–7 days | 7 daily snapshots guaranteed | Keep daily |
| 8–28 days | 4 weekly snapshots | Keep weekly |
| 1–12 months | 12 monthly snapshots | Keep monthly |
| 1–2 years | 2 annual snapshots | Keep annual |
List Available Snapshots
# List all snapshots
docker exec bizfirst-backup restic snapshots
# Example output:
# ID Time Host Tags
# -------------------------------------------------------------------------
# a1b2c3d4 2026-05-27 02:00:03 bizfirst-minio bizfirst-storage
# e5f6g7h8 2026-05-26 02:00:01 bizfirst-minio bizfirst-storage
# ...
# List with full details
docker exec bizfirst-backup restic snapshots --json | jq '.[].time'
# Find snapshot closest to a specific time
docker exec bizfirst-backup restic snapshots \
--tag bizfirst-storage \
--json | jq '.[] | select(.time >= "2026-05-20")'
Selective File Restore
Use this to recover one or a few specific files without restoring the entire bucket. The CID is the filename within the MinIO data directory structure.
Recover a Single Object by CID
# Find which snapshot contains the object (search by approximate date)
docker exec bizfirst-backup restic ls a1b2c3d4 | grep "3a7f2eb4c9"
# Restore only that object to a staging directory
docker exec bizfirst-backup restic restore a1b2c3d4 \
--target /tmp/restore-staging \
--include "*3a7f2eb4c9*"
# The file is now in /tmp/restore-staging — copy it back to MinIO
docker cp bizfirst-backup:/tmp/restore-staging/... .
mc cp ./recovered-file local/bizfirst-files/tenant_42/3a7f2eb4c9...
Recover All Objects for a Tenant
# Restore the entire tenant_42 prefix from yesterday's snapshot
docker exec bizfirst-backup restic restore latest \
--target /tmp/tenant-restore \
--include "*/tenant_42/*"
# Re-upload to MinIO
mc cp --recursive /tmp/tenant-restore/data/ local/bizfirst-files/
Recover Objects Modified Before a Timestamp
# Find the snapshot just before an incident (e.g. accidental batch delete at 14:30)
docker exec bizfirst-backup restic snapshots \
--tag bizfirst-storage \
--json | jq '.[] | select(.time < "2026-05-27T14:30:00")'
# Restore from that snapshot
docker exec bizfirst-backup restic restore SNAPSHOT_ID \
--target /tmp/pre-incident \
--include "*/bizfirst-files/*"
Full Bucket Restore
Use when the entire MinIO data volume is lost (disk failure, container volume corruption, or accidental deletion).
Stop the MinIO container
docker stop bizfirst-minio
Clear the damaged data volume
docker volume rm minio-data
docker volume create minio-data
Restore the snapshot into the new volume
docker run --rm \
-v minio-data:/restore-target \
-e RESTIC_REPOSITORY="$RESTIC_REPOSITORY" \
-e RESTIC_PASSWORD="$RESTIC_PASSWORD" \
-e AWS_ACCESS_KEY_ID="$B2_APPLICATION_KEY_ID" \
-e AWS_SECRET_ACCESS_KEY="$B2_APPLICATION_KEY" \
restic/restic:latest \
restore latest --target /restore-target --tag bizfirst-storage
Restart MinIO
docker start bizfirst-minio
Verify data integrity
mc ls local/bizfirst-files --recursive | wc -l
mc admin info local
Disaster Recovery Procedure
For a full host loss — new server, fresh MinIO install, restore from B2:
Provision new host and install Docker
Install Docker on the new host. Copy docker-compose.yml and .env from source control.
Set credentials from your secrets store
Set RESTIC_REPOSITORY, RESTIC_PASSWORD, B2_APPLICATION_KEY_ID, B2_APPLICATION_KEY, MINIO_ROOT_USER, MINIO_ROOT_PASSWORD.
Create the data volume and restore
docker volume create minio-data
docker run --rm \
-v minio-data:/restore-target \
-e RESTIC_REPOSITORY="$RESTIC_REPOSITORY" \
-e RESTIC_PASSWORD="$RESTIC_PASSWORD" \
-e AWS_ACCESS_KEY_ID="$B2_APPLICATION_KEY_ID" \
-e AWS_SECRET_ACCESS_KEY="$B2_APPLICATION_KEY" \
restic/restic:latest \
restore latest --target /restore-target
Start MinIO and verify
docker compose up -d minio
curl -f http://localhost:9000/minio/health/live
mc admin info local
Update DNS / load balancer to point to new host
Update the application's FileStorage__Endpoint if the MinIO hostname changed.
RTO & RPO Targets
| Incident | RPO (max data loss) | RTO (recovery time) |
|---|---|---|
| Container restart (no data loss) | 0 | < 2 minutes |
| Accidental object deletion | < 24 hours | < 1 hour |
| Disk volume corruption | < 24 hours | < 4 hours |
| Full host failure | < 24 hours | < 8 hours |
| Region outage (with B2 restore) | < 24 hours | < 8 hours |
Restore Verification
After any restore, verify that the recovered data is consistent:
# 1. Count objects in bucket
mc ls local/bizfirst-files --recursive | wc -l
# 2. Sample-test a known CID
mc stat local/bizfirst-files/tenant_42/3a7f2eb4c9...
# 3. Check MinIO server reports healthy
mc admin info local
# 4. Run a test store + retrieve via the application
# (call ExistsAsync on a known CID, then StoreAsync with new content)