Cómo migrar de MinIO a RustFS 1.0 con Docker
Índice de contenidos
- Puntos clave
- ¿Por qué ya no se descarga la imagen de MinIO?
- Qué es RustFS 1.0 y con qué licencia se publica
- ¿RustFS o Garage?
- Cómo he probado la migración
- Paso 1: levanta RustFS junto a MinIO
- Paso 2: pasa usuarios y políticas con la exportación IAM
- Paso 3: copia los buckets con rclone sync
- Paso 4: verifica recuentos y sumas de comprobación
- Paso 5: rehaz lo que la copia no lleva
- Paso 6: haz la pasada final y cambia los clientes
- ¿Cuánta memoria usa RustFS frente a MinIO?
- ¿Se puede arrancar RustFS sobre los datos de MinIO?
- Preguntas frecuentes
- ¿Puedo seguir usando MinIO con la imagen de Chainguard?
- ¿Conserva la migración las URL prefirmadas y las claves de las aplicaciones?
- ¿Cuánto tarda la copia de verdad?
- Conclusión
- Fuentes
Para migrar de MinIO a RustFS 1.0 con Docker, levanta RustFS junto a MinIO, importa los usuarios con mc admin cluster iam, copia los buckets con rclone sync –metadata y compáralos con rclone check –download. En mi prueba llegaron idénticos 4012 objetos; versiones, etiquetas y accesos públicos hubo que rehacerlos a mano.
Migré un MinIO con 4012 objetos a RustFS 1.0.0 con rclone sync y la comparación de sumas SHA-256 de los dos lados salió idéntica. RustFS es un servidor de almacenamiento de objetos compatible con S3, escrito en Rust y con licencia Apache 2.0, y es lo más parecido a MinIO que puedes montar hoy: consola web, usuarios IAM, versionado y bloqueo de objetos. Esta guía cubre la copia por S3 paso a paso, lo que se pierde por el camino y una segunda vía que conserva las versiones: arrancar RustFS sobre una copia del disco de MinIO. Lo probé el 27 de septiembre de 2026 con Docker. Tienes la versión en inglés de esta guía.
Puntos clave
- El 27 de septiembre de 2026 fallaron todas mis descargas de MinIO: Docker Hub responde que el repositorio no existe y Quay devuelve 401 incluso con la etiqueta fijada
RELEASE.2025-09-07T16-13-09Z. - RustFS 1.0.0 salió el 16 de septiembre de 2026, tras 14 meses de versiones alfa, beta y candidatas, con imagen para amd64 y arm64.
rclone sync --metadatacopió 4012 objetos y 335,7 MiB;rclone check --downloadno encontró diferencias. Sin--metadatase perdieronCache-Controly los metadatos propios.- Ni rclone ni
mc mirrorcopian las versiones antiguas, y rclone tampoco las etiquetas ni la política de acceso anónimo: esas tres cosas hay que rehacerlas en RustFS. - Los usuarios y políticas pasan con
mc admin cluster iam exporteimport, y el usuario importado entró en RustFS con su clave original. - RustFS 1.0.0 arrancó sobre una copia del volumen de MinIO y sirvió los 4016 objetos con las cinco versiones, las etiquetas y los usuarios. Su README marca esa compatibilidad como "Preview" y la documentación dice que es de un solo sentido.
¿Por qué ya no se descarga la imagen de MinIO?
Porque MinIO ya no publica imágenes gratuitas en ningún registro que funcione sin cuenta. El repositorio de MinIO en GitHub[1] está archivado desde el 25 de abril de 2026, y su README abre con "THIS REPOSITORY IS NO LONGER MAINTAINED". Estas son mis descargas del 27 de septiembre, a las 10:43 UTC:
$ docker pull minio/minio:latest
Error response from daemon: pull access denied for minio/minio,
repository does not exist or may require 'docker login'
$ docker pull quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
... HEAD request to https://quay.io/v2/minio/minio/manifests/
RELEASE.2025-09-07T16-13-09Z: 401 UNAUTHORIZED
La segunda línea es la novedad. El 16 de septiembre esa misma etiqueta de Quay todavía se descargaba, como cuenta la guía para migrar de MinIO a Garage, que repasa la retirada de Docker Hub con detalle. Si tu MinIO sigue vivo es porque la imagen está en la caché local de tu máquina, y un docker system prune o un servidor nuevo te deja sin ella.
La única imagen que encontré que se descarga sin cuenta es cgr.dev/chainguard/minio:latest. La compila Chainguard desde su bifurcación de MinIO[2], y el binario se identifica como RELEASE.2026-09-22T19-25-18Z. Solo existe la etiqueta latest: pedir la versión por su nombre devolvió not found.
El anuncio de Chainguard EmeritOSS[3] dice que la bifurcación se publica "in source form only" y que la imagen mantenida es un producto de pago, así que no cuentes con ella a largo plazo. Yo la usé como origen de esta prueba, fijada por su resumen sha256:bd014394.
Qué es RustFS 1.0 y con qué licencia se publica
RustFS es un servidor de objetos compatible con S3 que imita la forma de trabajar de MinIO. Usa los mismos puertos, 9000 para la API y 9001 para la consola, el mismo modelo de usuarios y políticas, y responde a buena parte de la herramienta mc. El fichero de licencia es Apache 2.0, y el README de RustFS[4] lo presenta como la alternativa que evita "the restrictions of AGPL", la licencia de MinIO.
La versión RustFS 1.0.0[5] se publicó el 16 de septiembre de 2026. Antes hubo 14 meses de preliminares, desde la 1.0.0-alpha.1 del 2 de julio de 2025 hasta la 1.0.0-rc.6 del 11 de septiembre. Las notas de la 1.0.0 son una lista de cambios de reparación, escáner y cifrado, sin texto que explique la versión.
El día de la prueba, el proyecto tenía 33 957 estrellas en GitHub y 12,1 millones de descargas en Docker Hub. Ya publica una 1.0.1-preview cada uno o dos días.
La compatibilidad con S3 está acotada por el propio proyecto. Su matriz de compatibilidad con S3[6] dice que RustFS "does not claim complete coverage of every standard or vendor-specific S3 behavior". En la etiqueta 1.0.0, la batería de pruebas s3-tests de Ceph tiene 460 casos que pasan, 21 pendientes y 274 excluidos. Entre los 21 pendientes están el registro de accesos del bucket (bucket logging) y los controles de propiedad (ownership controls).
¿RustFS o Garage?
RustFS es la opción si quieres el MinIO de siempre con otra licencia, y Garage si solo necesitas lo básico y quieres repartir los datos entre sitios distintos. La migración de MinIO a Garage tiene su propia guía; esta tabla resume en qué se separan:
| Criterio | RustFS 1.0.0 | Garage v2.4.1 |
|---|---|---|
| Licencia | Apache 2.0 | AGPLv3 |
| Versionado y bloqueo de objetos | Sí (probado el versionado) | No |
| Políticas de bucket y acceso anónimo | Sí (probado) | No |
| Consola web | Sí | No |
| Usuarios IAM de MinIO | Se importan con mc |
Modelo propio de claves |
| Leer el disco de MinIO | Sí, en vista previa | No |
Mi criterio cabe en dos frases. Si tus copias dependen del versionado o del bloqueo de objetos, o tus aplicaciones usan políticas y usuarios de MinIO, ve a RustFS. Si solo guardas ficheros de aplicaciones y copias de restic, Garage cubre eso y está pensado para nodos repartidos: su web lo vende como un almacén "so reliable you can run it outside datacenters".
Cómo he probado la migración
Monté los dos servidores en un proyecto de Compose desechable, en un contenedor de desarrollo linux/arm64 con 18 núcleos. Los tiempos son la mediana de cinco repeticiones con la máquina en reposo, cada una sobre un RustFS vacío, y la carga media de 1 minuto estuvo entre 0,63 y 2,81. En los comandos de esta guía he cambiado las credenciales y el nombre de la red por marcadores; el resto es lo que ejecuté.
En MinIO cargué con mc cuatro buckets:
app-data: 4004 objetos y 335,1 MiB, con 3000 JSON de 1 a 40 KB, 1000 ficheros aleatorios de 4 a 256 KB y 3 ficheros de 50 MiB subidos por partesversionado: cinco versiones del mismoconfig.txt, con el versionado activopublico: unindex.htmlcon descarga anónimabackups: un repositorio de restic 0.19.1 con una instantánea
Un objeto de app-data llevaba además Cache-Control, un metadato propio y dos etiquetas, y creé un usuario IAM app-backup con la política readwrite. Para copiar usé rclone 1.75.1, la última versión estable; como cliente mc usé cgr.dev/chainguard/minio-client, la única imagen de mc que se descargó.
Paso 1: levanta RustFS junto a MinIO
RustFS se añade como un servicio más del mismo Compose, con su propio volumen, para que los dos servidores se vean por la red interna. Este es el servicio que usé:
rustfs:
image: rustfs/rustfs:1.0.0
environment:
RUSTFS_ACCESS_KEY: mi_usuario_rustfs
RUSTFS_SECRET_KEY: mi_clave_rustfs
RUSTFS_CONSOLE_ENABLE: "true"
volumes:
- rustfs-data:/data
ports:
- "127.0.0.1:22210:9000"
- "127.0.0.1:22211:9001"
Declara también rustfs-data en la sección volumes: del fichero y arranca con docker compose up -d rustfs. Sin credenciales, RustFS arranca con rustfsadmin/rustfsadmin y avisa al iniciar. Si reutilizas tu fichero de MinIO, RustFS también acepta MINIO_ROOT_USER y MINIO_ROOT_PASSWORD: lo probé y la clave por defecto dejó de funcionar.
La imagen corre como el usuario 10001. Con un volumen con nombre no hay nada que hacer, pero si montas una carpeta del host tiene que ser de 10001:10001, como explica el README. La consola queda en http://127.0.0.1:22211/rustfs/console/; la raíz del puerto devuelve 403.
Paso 2: pasa usuarios y políticas con la exportación IAM
Los usuarios, grupos y políticas de MinIO pasan a RustFS con un ZIP. Con dos alias de mc, viejo para MinIO y nuevo para RustFS, exporta en uno e importa en el otro:
mc admin cluster iam export viejo
mc admin cluster iam import nuevo viejo-iam-info.zip
La importación respondió Added users: app-backup y Added policies for users: app-backup. Después, el usuario app-backup listó los buckets de RustFS con la AWS CLI y su clave de siempre, así que las aplicaciones no necesitan credenciales nuevas. La consola de RustFS tiene la misma función en Import/Export.

No todo mc admin funciona contra RustFS. mc admin user add y mc admin policy attach funcionaron, pero mc admin info nuevo devolvió Unable to get service info.
Paso 3: copia los buckets con rclone sync
rclone copia de un servidor S3 a otro sin pasar por tu disco, y crea en el destino los buckets que falten. Define los dos remotos en un fichero de variables de entorno; rclone 1.75.1 no tiene un proveedor RustFS, así que el destino va como Other:
RCLONE_CONFIG_VIEJO_TYPE=s3
RCLONE_CONFIG_VIEJO_PROVIDER=Minio
RCLONE_CONFIG_VIEJO_ENDPOINT=http://minio:9000
RCLONE_CONFIG_VIEJO_ACCESS_KEY_ID=mi_usuario_minio
RCLONE_CONFIG_VIEJO_SECRET_ACCESS_KEY=mi_clave_minio
RCLONE_CONFIG_NUEVO_TYPE=s3
RCLONE_CONFIG_NUEVO_PROVIDER=Other
RCLONE_CONFIG_NUEVO_ENDPOINT=http://rustfs:9000
RCLONE_CONFIG_NUEVO_ACCESS_KEY_ID=mi_usuario_rustfs
RCLONE_CONFIG_NUEVO_SECRET_ACCESS_KEY=mi_clave_rustfs
Guárdalo como rclone.env y lanza rclone en la red del proyecto. viejo: y nuevo: sin bucket significan todos los buckets:
docker run --rm --network mi_proyecto_default \
--env-file rclone.env rclone/rclone:1.75.1 \
sync viejo: nuevo: --metadata --transfers 8 -v
La opción --metadata es la que importa. Sin ella, el objeto de prueba llegó a RustFS solo con Content-Type: perdió Cache-Control y el metadato propio X-Amz-Meta-Proyecto. Con ella llegaron los tres, y la documentación del backend S3 de rclone[7] lista qué cabeceras trata como metadatos del sistema.
El resumen de la copia fue este:
Transferred: 335.729 MiB / 335.729 MiB, 100%, 166.784 MiB/s
Checks: 0 / 0, -, Listed 4067
Transferred: 4012 / 4012, 100%
Elapsed time: 2.0s
Paso 4: verifica recuentos y sumas de comprobación
Una copia se da por buena cuando los recuentos, los tamaños y el contenido coinciden en los dos lados. rclone check compara tamaños y sumas MD5, y con --download descarga los dos lados y los compara byte a byte:
rclone check viejo: nuevo:
rclone check viejo: nuevo: --download
El primero dio 4012 coincidencias, 0 diferencias y "3 hashes could not be checked". Son los tres ficheros de 50 MiB: MinIO los guardó por partes, y la ETag de un objeto multiparte no es su MD5. La pasada con --download los cubrió y dio 4012 coincidencias sin diferencias.
Como segunda prueba, independiente de rclone, saqué la suma SHA-256 de cada objeto en los dos servidores y comparé las listas:
rclone hashsum sha256 --download viejo: | sort -k2 > viejo.txt
rclone hashsum sha256 --download nuevo: | sort -k2 > nuevo.txt
diff viejo.txt nuevo.txt && echo IDENTICOS
Salieron 4012 líneas por lado y IDENTICOS. rclone size por bucket también coincidió: 4004 objetos y 351 378 737 bytes en app-data, y los mismos seis objetos del repositorio de restic.
Paso 5: rehaz lo que la copia no lleva
La copia por S3 lleva los datos y los metadatos, pero no la configuración de los buckets ni el historial. Esto es lo que comprobé en RustFS después del rclone sync:
| Qué tenías en MinIO | Tras rclone sync --metadata |
Cómo lo recuperé |
|---|---|---|
Datos, Content-Type, Cache-Control y metadatos propios |
Llegan | Nada que hacer |
| Etiquetas de objeto | Se pierden | mc tag set o mc mirror -a |
| Versiones antiguas | Solo llega la actual | Arranque sobre el disco (abajo) |
| Versionado del bucket | Desactivado | mc version enable |
| Descarga anónima | Privado (403) | mc anonymous set download |
| Usuarios y políticas IAM | No van por S3 | Paso 2 |
Tras mc anonymous set download nuevo/publico, la descarga sin firmar pasó de 403 a 200, y tras mc version enable el bucket versionado volvió a guardar versiones nuevas. Si usas etiquetas, mc mirror -a las conservó en mi prueba, a diferencia de rclone y de mc mirror sin esa opción. Ojo: mc mirror hacia un bucket concreto que no existe falla con "The specified bucket does not exist"; créalo antes con mc mb.
Paso 6: haz la pasada final y cambia los clientes
Una segunda pasada de rclone sync copia solo lo que cambió desde la primera, así que la parada del servicio dura lo que tarde esa pasada. En la prueba modifiqué un objeto, añadí nueve y borré cinco en MinIO. La segunda pasada copió 10 objetos, borró 5 y tardó 0,5 s en las cinco repeticiones, con 4012 comprobaciones. rclone check --download volvió a dar 0 diferencias.
La trampa apareció en mi primera prueba, donde esa pasada borró un sexto objeto. rclone sync deja el destino idéntico al origen, así que eliminó prueba/p.txt, un fichero que yo había subido directamente a RustFS durante las pruebas. Hasta que cortes, no escribas nada en RustFS que no esté en MinIO.
El orden que seguiría en producción es este:
- Para las aplicaciones que escriben en MinIO
- Lanza la última pasada de
rclone syncy elrclone check --download - Cambia el punto de acceso a RustFS en cada cliente (las claves no cambian si importaste el IAM)
- Arranca las aplicaciones y deja MinIO parado, sin borrarlo, unos días
Probé dos clientes contra RustFS con el usuario importado. La AWS CLI 2.37.4 listó, subió, leyó cabeceras y generó una URL prefirmada que descargó el objeto, mientras que la misma URL sin firma devolvió 403. Con restic 0.19.1, restic check --read-data sobre el repositorio migrado respondió "no errors were found", y una copia nueva de 1000 ficheros se guardó sin errores.
¿Cuánta memoria usa RustFS frente a MinIO?
RustFS usó entre 2,4 y 3,5 veces más memoria que MinIO con los mismos datos. La medí con docker stats, diez muestras por momento con un segundo de pausa, y la tabla da la mediana en MiB:
| Momento | MinIO | RustFS |
|---|---|---|
| 60 s después de reiniciar los dos, con los datos cargados | 68 | 236 |
| Justo después de cada copia completa (5 copias, 50 muestras) | 401 | 974 |
| Tras 3 minutos en reposo después de la última copia | 388 | 1253 |
Las muestras de cada fila variaron poco: RustFS se movió entre 857 y 1110 MiB justo después de las copias, y MinIO entre 387 y 467. RustFS siguió creciendo en reposo tras la última copia, de 974 a 1253 MiB de mediana, y no investigué por qué. Si tu MinIO vive en una máquina con poca memoria, mide RustFS con tus datos antes de cortar.
¿Se puede arrancar RustFS sobre los datos de MinIO?
Sí, en mi prueba funcionó, y conserva lo que la copia por S3 pierde. Paré MinIO, copié su volumen a uno nuevo con el dueño que espera RustFS y arranqué la imagen rustfs/rustfs:1.0.0 normal sobre esa copia:
docker run --rm --entrypoint sh -u 0 \
-v mi_proyecto_minio-data:/from:ro -v rustfs-sobre-minio:/to \
rclone/rclone:1.75.1 \
-c 'cp -a /from/. /to/ && chown -R 10001:10001 /to'
docker run -d --name rustfs-sobre-minio \
--network mi_proyecto_default \
-e RUSTFS_ACCESS_KEY=mi_usuario_minio \
-e RUSTFS_SECRET_KEY=mi_clave_minio \
-v rustfs-sobre-minio:/data rustfs/rustfs:1.0.0
La primera orden usa la imagen de rclone solo porque trae sh y cp; cualquier imagen con shell sirve. La guía de volúmenes y bind mounts en Docker explica en qué se diferencia un volumen con nombre de una carpeta del host.
RustFS listó los cuatro buckets y sirvió los 4016 objetos que tenía MinIO en ese momento, con sumas SHA-256 idénticas. También conservó las cinco versiones de config.txt con sus identificadores, las etiquetas, Cache-Control, la descarga anónima de publico y el usuario app-backup. restic check --read-data pasó, y un objeto escrito después sobrevivió a un reinicio.
Hay tres motivos para hacerlo solo sobre una copia:
- La documentación de compatibilidad con el formato de MinIO[8] lo dice claro: "Migration is one-way (MinIO to RustFS)". RustFS crea su propia carpeta
.rustfs.sysjunto a.minio.sys, y un MinIO no lee lo que RustFS escribe. - El README marca esta función como "Preview" y dice que no está en la compilación por defecto. La misma tabla de compatibilidad, en cambio, da la lectura de objetos sin cifrar como soportada en esa compilación, y es lo que vi. Los objetos que MinIO cifró (SSE) no se pueden leer.
- Mi prueba fue con un solo disco, sin conjuntos de borrado ni cifrado. Con más de un disco o nodo, la geometría tiene que coincidir, y eso no lo probé.
El registro de RustFS repitió cada 5 s el aviso "Ignoring unknown persisted scalar config key" por una opción de escáner de MinIO que no reconoce. No afectó a los datos.
Preguntas frecuentes
¿Puedo seguir usando MinIO con la imagen de Chainguard?
Hoy sí: cgr.dev/chainguard/minio:latest se descargó sin cuenta el 27 de septiembre de 2026 y arrancó sin problemas. Pero solo publica latest, no hay etiquetas por versión, y Chainguard presenta la imagen mantenida como un producto comercial. Fíjala por resumen y úsala para ganar tiempo, no como plan.
¿Conserva la migración las URL prefirmadas y las claves de las aplicaciones?
Las claves sí, si importas el IAM como en el paso 2: el usuario importado entró en RustFS con su clave de MinIO. Las URL prefirmadas ya emitidas llevan en la firma el nombre del servidor y caducan, así que no probé a reutilizarlas: genera nuevas contra RustFS.
¿Cuánto tarda la copia de verdad?
En mi prueba, 335,7 MiB en 2,0 s de mediana entre dos contenedores de la misma máquina, sin red de por medio. En las cinco copias, rclone contó entre 1,9 y 2,1 s. Entre máquinas distintas pesará la red, y la cifra que decide la parada es la de la segunda pasada: 0,5 s para diez cambios sobre 4012 objetos.
Conclusión
Migrar de MinIO a RustFS 1.0 con Docker son cuatro piezas: RustFS al lado, el IAM con mc, los datos con rclone sync --metadata y la verificación con rclone check --download. En mi prueba, todo lo que viaja por S3 llegó intacto. Versiones, etiquetas y políticas de acceso hubo que rehacerlas o recuperarlas arrancando RustFS sobre una copia del disco.
RustFS tiene 11 días de versión estable al escribir esto, así que migra con MinIO parado pero intacto y una vuelta atrás preparada. Si no necesitas versionado ni políticas, compara antes con la guía de Garage, y si vienes de la instalación de MinIO con Docker, esta es la salida más directa.
Fuentes
- repositorio de MinIO en GitHub
- bifurcación de MinIO
- anuncio de Chainguard EmeritOSS
- README de RustFS
- RustFS 1.0.0
- matriz de compatibilidad con S3
- documentación del backend S3 de rclone
- documentación de compatibilidad con el formato de MinIO
- RustFS, pruebas s3-tests pendientes en 1.0.0
- rustfs/rustfs en Docker Hub
Código fuente
Accede a todo el código fuente de este artículo en GitHub.
Ver en GitHub