Portal Community
Before you restore Restores read from Backblaze B2 — ensure the 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

  1. Snapshot Model
  2. List Available Snapshots
  3. Selective File Restore
  4. Full Bucket Restore
  5. Disaster Recovery Procedure
  6. RTO & RPO Targets
  7. Restore Verification

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 AgeAvailabilityPolicy
0–7 days7 daily snapshots guaranteedKeep daily
8–28 days4 weekly snapshotsKeep weekly
1–12 months12 monthly snapshotsKeep monthly
1–2 years2 annual snapshotsKeep 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
This deletes all current data Only proceed if the volume is confirmed corrupted or intentionally being replaced from backup.

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

IncidentRPO (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
RPO assumes daily backups ran successfully Data written after the last successful backup snapshot will be lost in a full volume failure. Verify nightly backup completion in your daily checklist. See Maintenance.

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)