Skip to main content
← All posts

Migrating from MinIO to RustFS: A Technical Guide

December 7, 20259 min read
Best PracticesGeneral Usage

Revised October 2026. This is the current recommended migration path. The copy procedure revises a December 2025 contribution from soakes.

Move common S3 workloads from MinIO onto a new RustFS 1.0 deployment by copying objects over the S3 API. Keep the MinIO source intact until verification passes, then point clients at the RustFS endpoint.

RustFS covers common S3 workflows: bucket and object operations, listing, multipart upload, versioning, lifecycle, tags, IAM, bucket policies, and server-side encryption workflows. It is not identical to every AWS S3 or MinIO API. Read the known compatibility differences and validate the operations your application uses against the target release.

This guide does not promise zero downtime, an SLA, or a price. It does not replace a MinIO data directory with a current RustFS binary.

Which page to follow

PageUse it for
This guideThe recommended path onto a current RustFS 1.0 release.
Binary replacement, 18 March 2026A historical example for RustFS 1.0.0-alpha.89 only.
RustFS 1.0.0 GAWhat the 1.0.0 release shipped.
GitHub releasesThe tag to install. Confirm it before a production cutover.

Released RustFS binaries and container images do not include the special-purpose rio-v2 build used for MinIO on-disk reads. Do not point a current rustfs/rustfs image at a MinIO data directory and treat that as the migration.

Version expectations

Source. A MinIO deployment you can read with AWS Signature Version 4 credentials. This guide does not certify a specific MinIO RELEASE tag, and MinIO administrative APIs are a separate surface from the S3 data plane. Inventory the source version you actually run, including whether buckets use versioning, Object Lock, default encryption, or an external KMS.

Target. RustFS 1.0.0, generally available on 16 September 2026, or a later 1.0 patch. The example below uses the explicit image rustfs/rustfs:1.0.3, published on 17 October 2026. That patch keeps the 1.0.2 server code and updates the embedded Console. Check current releases before you pull, and pin the tag you verified. Do not install 1.0.0-alpha.89 for a new migration.

Client. The MinIO client mc, used here as an S3 client (alias, ls, mirror, diff, stat, cp), or the AWS CLI with --endpoint-url. Do not use mc admin against RustFS as the migration interface.

Topology limits

The copy does not preserve MinIO's drive layout. Stand up RustFS on its own volumes. The target does not have to use the same drive count as the source. Parity reduces usable capacity relative to raw disk; size the target from the erasure-coding configuration docs.

Documented layout rules:

  • A single-drive pool has automatic parity EC:0. The host is the failure domain. The Compose example below is that layout, so you can rehearse the copy. It is not a production durability plan.
  • Multi-drive erasure sets contain 2 to 16 drives. The multiple-node, multiple-disk installation documents a production cluster as at least four servers, each with at least one disk.
  • RUSTFS_VOLUMES must be identical on every node, including endpoint order. RustFS rejects a later change to endpoint count, order, or RUSTFS_ERASURE_SET_DRIVE_COUNT.
  • With more than one volume argument, every argument needs an ellipsis. Each pool must expand to at least two drive endpoints. A single-drive pool cannot join a multi-pool deployment. See cluster lifecycle.
  • Docker's default bridge network does not support multi-node RustFS. Multi-node containers use host networking, as described in the Docker installation docs.
  • Do not place RustFS volumes on NFS. The Linux prerequisites recommend XFS for data disks.

What does not migrate automatically

mc mirror copies current object bytes. Public mc documentation describes that command as synchronizing the current object, without version history. Treat user metadata and tags as unverified until you spot-check them. Bucket configuration, identity, and replication do not come along with the object copy.

ItemWhat to expect
Current object bytesCopied by mc mirror after a successful final pass.
User metadata and tagsNot guaranteed. Compare mc stat on a sample before cutover.
Older versions and delete markersNot copied by a plain mirror. Count versions on both sides if the source bucket is versioned.
Object Lock retention and legal holdNot established by the mirror. Enable Object Lock on the destination bucket before copying locked data, then verify a sample.
Bucket policy, lifecycle, CORS, website, loggingExport from the source and reapply. Bucket access logging and ownership controls are not equivalent to AWS S3.
ACL grant policiesNot the RustFS authorization model. Canned ACL headers are only partial. Use IAM and bucket policies.
Event notificationsReconfigure on RustFS.
Bucket replication and site replicationReconfigure after the data copy. The mirror does not move the replication topology.
IAM users, groups, policies, and service accountsRecreate on RustFS. The root key used for the copy is not an application credential.
LDAP, OIDC, and STSReconfigure. Nothing in this procedure imports those providers.
MinIO server configuration and mc admin stateStays on MinIO.
In-progress multipart uploadsFinish or abort them on the source before the final copy.
Objects the S3 client cannot decryptStay behind. KES, MinKMS, or another external key service can leave ciphertext the client cannot read. Bucket default encryption can encrypt objects even when uploaders set no SSE header, so inventory encryption before you assume a bucket is plaintext.
Transitioned objectsCopy them only when a GET through MinIO returns the bytes you intend to store.

1. Back up

Take the backup you would need if the cutover were postponed.

  • Snapshot or otherwise back up the MinIO data disks and the service configuration before you stop writers.
  • Record the bucket list, versioning state, Object Lock state, bucket policies, lifecycle rules, notification targets, and the identity provider in use.
  • Keep MinIO installed and its data directory unchanged. This procedure never formats those disks and never writes the migration through them.
  • Store the RustFS Compose file and the access key you set on the target. Replace the placeholder secrets before the file is shared.

2. Quiesce writes

Stop application writers. Let in-flight multipart uploads complete, or abort them. A mirror started while clients are still writing can miss objects created after that pass begins.

An earlier one-shot mc mirror can shrink how much data the final pass moves. Stop that command before the final copy. mc mirror --watch keeps watching the source until you terminate it; it does not remove the need to stop writers, run a final copy, and verify. Do not pass --remove. That flag deletes destination objects that are absent from the source.

3. Deploy the RustFS target

Use empty RustFS volumes. The service, volume, and network names below refer to the same keys.

Pin rustfs/rustfs:1.0.3 only after you confirm that tag on the releases page. Set RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY to values other than the image default rustfsadmin. MinIO-style MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are accepted only when the canonical variables are unset, and they are deprecated. See credential management.

services:
  rustfs:
    image: rustfs/rustfs:1.0.3
    container_name: rustfs
    hostname: rustfs
    environment:
      RUSTFS_VOLUMES: /data
      RUSTFS_ADDRESS: ":9000"
      RUSTFS_CONSOLE_ENABLE: "true"
      RUSTFS_CONSOLE_ADDRESS: ":9001"
      RUSTFS_ACCESS_KEY: replace-with-your-access-key
      RUSTFS_SECRET_KEY: replace-with-your-secret-key
      RUSTFS_REGION: us-east-1
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - rustfs-data:/data
    networks:
      - rustfs

networks:
  rustfs:
    driver: bridge

volumes:
  rustfs-data:

RUSTFS_VOLUMES=/data matches the mounted volume. This is one local drive. Readiness is an unauthenticated probe on the S3 port, not the Console port. From the host:

curl -fsS http://127.0.0.1:9000/health/ready

A 200 means storage, IAM, and peer health are ready. A 503 means they are not. The probe is necessary before the copy and is not evidence that any object was migrated. The status check docs describe the response.

Leave MinIO on its existing endpoint. The two services are separate S3 endpoints for the copy.

4. Copy

Install mc on a host that can reach both endpoints. Use root credentials for this window so the client can create missing buckets and read the source namespace. Create versioned or Object Lock buckets on RustFS before the mirror when the source relies on those settings, and confirm the calls against the target release.

mc alias set minio-old https://minio.example.com SOURCE_ACCESS_KEY SOURCE_SECRET_KEY
mc alias set rustfs-new http://127.0.0.1:9000 TARGET_ACCESS_KEY TARGET_SECRET_KEY

mc ls minio-old
mc ls rustfs-new

mc mirror --dry-run minio-old/production-data rustfs-new/production-data
mc mirror --overwrite minio-old/production-data rustfs-new/production-data

Repeat the mirror for each bucket. --dry-run lists the work and does not write it. --overwrite replaces a destination object when the source copy is the one you want to keep. Without --overwrite, mc mirror skips an object that already exists on the destination, logs an error, and continues.

Path-style addressing is the RustFS default. Set the client endpoint explicitly. Set the region to us-east-1, or to the RUSTFS_REGION you configured. Virtual-hosted-style URLs also need RUSTFS_SERVER_DOMAINS.

After the bytes are on RustFS, reapply bucket policies, lifecycle rules, CORS, notifications, and replication from the inventory you saved. Create IAM users for applications and retire the root key from client configuration.

5. Verify

Opening the Console at port 9001 only shows that the process is serving the UI. Use the checks below before you send traffic.

curl -fsS http://127.0.0.1:9000/health/ready

mc diff minio-old/production-data rustfs-new/production-data

mc ls --recursive minio-old/production-data | wc -l
mc ls --recursive rustfs-new/production-data | wc -l

mc stat minio-old/production-data/path/to/object
mc stat rustfs-new/production-data/path/to/object

mc cp minio-old/production-data/path/to/object ./source-object
mc cp rustfs-new/production-data/path/to/object ./target-object
sha256sum ./source-object ./target-object

Read the results as follows:

  • mc diff with no output means the client reported no listing differences. It is not a byte-for-byte proof.
  • The recursive counts should match for the buckets you copied. A versioned bucket needs a separate version count; a plain mirror did not copy older versions.
  • Compare size and the checksum you compute. ETags can differ when the multipart layout changes, so ETag equality alone is not the success test.
  • mc stat is the spot check for user metadata and tags. Re-copy or reapply metadata when a sample your application needs does not match.
  • Run a read-only pass of the application against the RustFS endpoint, using the same SDK calls production uses.

Cut over by changing the S3 endpoint in client configuration. Keep path-style and the region aligned with the server. Watch errors before you allow writers.

6. Roll back

Rollback returns clients to MinIO.

  • Point applications back at the MinIO endpoint and credentials.
  • Leave the MinIO data directory in place. Do not delete it until the verification window you planned has passed.
  • To discard a bad RustFS copy, remove the new rustfs-data volume and repeat the deploy and copy. That deletes the destination copy only.
  • There is no second restore step on MinIO, because this procedure does not write to it.

Further reading

MinIO is a registered trademark of MinIO, Inc. RustFS is not affiliated with, endorsed by, or sponsored by MinIO, Inc.