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.
- Prereqs: 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
# Example restores later 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 (keep running)
mc mirror --watch --overwrite primary/data backup/data
Caution:
- Add
--removeonly 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.
- 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
mc ls --recursive primary/data | wc -l
mc ls --recursive backup/data | wc -l
# 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
for i in $(seq 1 100); do echo "file $i" | mc pipe 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.
- diff shows no differences.
- Commands and timings are recorded for later automation.
Common mistakes
- Not enabling versioning before critical changes.
- Using
--removeon 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.