## Intro

This guide shows how to back up and restore MinIO with commands you can run today. You will learn a simple production workflow, how to validate results, how to plan rollbacks, and what mistakes to avoid. The examples use the MinIO Client (mc) so you can pilot locally before rolling out to servers, Docker, or Kubernetes.

What you will get:

- Clear backup and restore patterns you can automate.

- Concrete commands for snapshots, continuous mirrors, and validation.

- A narrow local pilot you can complete in under an hour.

## Workflow Overview

A reliable MinIO backup and restore flow:

- Inventory what to protect

- Object data: all buckets that matter.

- Version history: enables point-in-time recovery.

- Credentials and policies: users, groups, access rules.

- Encryption keys and settings if you use SSE-KMS.

- Choose a backup pattern

- Periodic snapshots to immutable, dated prefixes.

- Continuous mirroring for a warm standby.

- Hybrid: both, to cover point-in-time and near-zero RPO.

- Enable guardrails

- Bucket versioning on critical data.

- Optional object retention to prevent accidental deletes.

- Automate and schedule

- Run backups on an interval or continuously for mirrors.

- Log results and alert on failures.

- Validate

- Compare counts, sizes, and differences.

- Spot check object metadata.

- Document restore and rollback

- Exact commands and ordering.

- Prerequisites: keys, users, and policies.

- A short restore rehearsal checklist.

## Requirements and assumptions

- MinIO Client (mc) installed and network access to your MinIO endpoints.

- Sufficient capacity at the backup destination (another MinIO, S3-compatible store, or an object gateway on-prem).

- If you use server-side encryption with a KMS, back up the keys and config. Losing keys makes encrypted data unrecoverable.

- Use non-root test credentials for pilots and least privilege in production.

## Practical backup patterns

### Pattern A: periodic snapshots (dated prefixes)

Use a dated snapshot prefix for point-in-time recovery.

# Aliases (adjust endpoints and credentials)
mc alias set primary http://localhost:9000 minio minio123
mc alias set backup http://localhost:9002 minio minio123

# Enable versioning on critical buckets (optional but recommended)
mc version enable primary/data

# Snapshot to a dated prefix
DATE=$(date -u +%Y%m%dT%H%M%SZ)
mc mirror --overwrite primary/data backup/snapshots/$DATE 
 Later restores can target backup/snapshots/20260101T000000Z .

Notes:

- Snapshots do not delete older backups. Use lifecycle rules on the backup side to expire old snapshots if needed.

- Keep snapshots read-only for safety where possible.

### Pattern B: continuous mirroring (warm standby)

Keep a near-real-time copy at a secondary endpoint.

# One-time full sync
mc mirror --overwrite primary/data backup/data

# Continuous updates (run in foreground; consider a process manager for production)
mc mirror --watch --overwrite primary/data backup/data 
 Caution:

- Add --remove only if you want deletes on primary to propagate to backup. Understand the risk before enabling it.

### Guardrails that improve recovery

# Enable versioning
mc version enable primary/data

# Optional: governance retention for 30 days on all objects
# Adjust as needed for compliance and workloads
mc retention set governance 30d primary/data 

### Configuration and identity backups

 Keep everything you need to rebuild an endpoint:

- Environment files or manifests that set root credentials and server options.

- Users, groups, and policies. Record how to recreate them; for example:

mc admin user list primary
 mc admin policy list primary 

- If you use a KMS, keep keys and connection settings safe and recoverable.

## Restore and disaster recovery

### Cold restore from a dated snapshot

 When the primary is healthy but data needs to be rolled back:

# Choose a snapshot point-in-time and mirror it back
SNAP=20260101T000000Z
mc mirror --overwrite backup/snapshots/$SNAP primary/data 

### Warm failover using the mirror

 If primary is down, point applications to backup/data . After primary is rebuilt, reverse mirror to repopulate it:

# After rebuilding primary with the same or compatible config
mc mirror --overwrite backup/data primary/data 

### Restoring configuration

- Recreate users and policies as recorded. Validate access with a small object read and write.

- Restore KMS keys and settings before reading encrypted objects.

## Validation checks

 Run these after each backup job and before declaring a restore complete.

# Count objects (write to file then count)
mc ls --recursive primary/data > primary_list.txt
wc -l primary_list.txt
mc ls --recursive backup/data > backup_list.txt
wc -l backup_list.txt

# Compare total size
mc du primary/data
mc du backup/data

# Find differences
mc diff --recursive primary/data backup/data

# Spot check a few objects
mc stat primary/data/path/to/object
mc stat backup/data/path/to/object 
 Tips:

- Automate at least counts, size, and diff. Alert on mismatches.

- ETag may not equal MD5 for multipart uploads; use diff and size checks for confidence.

## Rollback planning

### With versioned buckets

List versions and restore a specific one:

# Inspect versions
mc ls --versions primary/data/path/to/object

# Restore a chosen version over the current one
mc cp --version-id <VERSION_ID> \
 primary/data/path/to/object \
 primary/data/path/to/object 

### With snapshot backups

 Rewind a bucket by mirroring a known-good snapshot:

SNAP=20260101T000000Z
mc mirror --overwrite backup/snapshots/$SNAP primary/data 
 Always dry-run on a test bucket first, then perform the rollback on production with a maintenance window where appropriate.

## Local Pilot Plan

A small, measurable pilot proves the workflow and surfaces tuning needs.

- Start two local MinIO containers

# Primary on 9000
 docker run -d --name minio1 -p 9000:9000 \
 -e MINIO_ROOT_USER=minio -e MINIO_ROOT_PASSWORD=minio123 \
 quay.io/minio/minio server /data

 # Backup on 9002
 docker run -d --name minio2 -p 9002:9000 \
 -e MINIO_ROOT_USER=minio -e MINIO_ROOT_PASSWORD=minio123 \
 quay.io/minio/minio server /data 

- Configure mc and create test data

 mc alias set primary http://localhost:9000 minio minio123
 mc alias set backup http://localhost:9002 minio minio123

 mc mb primary/data
 # Create a few test objects without pipelines
 for i in $(seq 1 100); do
 echo "file $i" > /tmp/obj-$i.txt
 mc cp /tmp/obj-$i.txt primary/data/obj-$i.txt
 done 

- Run a one-time backup and validate

 mc mirror --overwrite primary/data backup/data
 mc du primary/data && mc du backup/data
 mc diff --recursive primary/data backup/data 

- Simulate loss and restore

 # Simulate deletion on primary
 mc rm --recursive --force --older-than 0s primary/data/obj-1.txt

 # Restore from backup
 mc mirror --overwrite backup/data primary/data

 # Validate
 mc diff --recursive primary/data backup/data 

- Try a dated snapshot

 DATE=$(date -u +%Y%m%dT%H%M%SZ)
 mc mirror --overwrite primary/data backup/snapshots/$DATE 
 Success criteria:

- Object counts and sizes match after backup and after restore.

- mc diff shows no differences.

- Commands and timings are recorded for later automation.

## Common mistakes

- Not enabling versioning before critical changes.

- Using --remove on mirror without understanding it propagates deletes.

- Forgetting to back up credentials, policies, and any encryption keys.

- Not testing restores until an outage happens.

- Assuming ETag always equals MD5 (it may differ for multipart uploads).

- Skipping validation and logging of every run.

## Conclusion

Start with a narrow local pilot, then scale the same pattern to production. Keep versioning on, protect keys and configs, and validate every backup and every restore. Document the exact commands for restores and rehearse them so you can meet your recovery objectives with confidence.