Tutoriel

Migrer MinIO vers Garage ou RustFS sans perdre un objet courant

Self-hosting13 min de lecture20 étapes

Le dépôt MinIO est archivé depuis le 25 avril 2026 : votre stockage S3 tourne désormais sans correctif de sécurité en amont. Garage et RustFS sont les deux cibles auto-hébergeables qui reviennent, mais la copie des objets n'est que la moitié du travail. Les politiques IAM, l'historique des versions et les URLs présignées ne suivent pas. Ce guide inventorie la source, copie avec rclone, prouve le résultat par des comptes et des contrôles, puis bascule l'application en trois temps, avec une coupure d'écriture minimale et un retour arrière prêt.

Sommaire· Pourquoi ne pas laisser MinIO là où il est1/14
  1. 01Pourquoi ne pas laisser MinIO là où il est
  2. 02Ce qu'une copie de bucket ne déplace pas toute seule
  3. 03Prérequis et plan de capacité
  4. 04Étape 1 : inventorier la source avant de copier
  5. 05Garage et RustFS : les écarts à connaître avant de choisir
  6. 06Versioning : ce que la copie perd, et que faire
  7. 07Étape 2 : préparer la cible, Garage ou RustFS
  8. 08Étape 3 : copier avec rclone et prouver le résultat
  9. 09ETag multipart et mc mirror : lire les écarts sans se tromper
  10. 10URLs présignées : pourquoi elles tombent à la bascule
  11. 11Étape 4 : basculer en trois temps, sans coupure franche
  12. 12Le retour arrière tient en une variable
  13. 13Dépannage : les symptômes qui reviennent
  14. 14La documentation officielle

Pourquoi ne pas laisser MinIO là où il est

Le dépôt minio/minio a été archivé par son propriétaire le 25 avril 2026 : il est en lecture seule, son README annonce que le projet n'est plus maintenu et précise que les binaires déjà publiés ne recevront plus de mises à jour. Concrètement, la prochaine faille de votre serveur S3 ne sera corrigée par personne en amont. Le client mc l'a été le 14 juillet 2026.

Votre MinIO continue de fonctionner : rien ne casse le jour de l'archivage. Mais un stockage objet est exposé et tourne désormais sans correctif de sécurité. Deux cibles auto-hébergeables reviennent dans les discussions : Garage, publié sous AGPLv3, et RustFS, publié sous licence Apache 2.0.

L'installation de chacune a son guide : Garage sur un VPS et RustFS sur un VPS. Ici, on part d'un MinIO en production : déplacer les données, prouver que rien ne manque, basculer sans URL cassée.

Ce qu'une copie de bucket ne déplace pas toute seule

  • Les objets courants — c'est la partie facile : rclone ou mc mirror les copient, avec un contrôle à faire ensuite.
  • Les anciennes versions — la documentation de mc mirror précise qu'il ne synchronise que l'objet courant, sans information de version.
  • Les utilisateurs et les politiques IAM — ils vivent dans MinIO, pas dans les buckets. Les secrets ne s'exportent pas : on régénère des clés côté cible.
  • Les URLs présignées déjà distribuées — la signature dépend de l'hôte, de la région et des clés. Un changement d'endpoint les invalide.
  • Les écarts de compatibilité S3 — ACL, politiques de bucket, accès anonyme, versioning : chaque cible a ses trous, à lire dans sa documentation plutôt qu'à supposer.
  • La configuration des clients — endpoint, région, adressage path-style : tout ce que votre application, vos sauvegardes restic ou votre CDN ont en dur.

Prérequis et plan de capacité

Il vous faut un accès administrateur à MinIO, un poste ou un VPS avec mc et rclone, et une cible déjà installée et joignable en HTTPS (voir les deux guides ci-dessus pour le reverse proxy et le certificat). La règle de capacité est simple : tant que vous n'avez pas validé la migration, vous gardez la source intacte, donc vous payez le disque deux fois.

Notre recommandation : prévoir sur la cible la taille des données de la source plus une marge d'environ 30 %. Sur le même VPS, cela fait au moins deux fois le volume actuel plus la marge ; sur deux VPS, chacun porte sa part. Un nœud Garage unique avec replication_factor = 1 ne garde qu'une copie de chaque objet : ce n'est pas une sauvegarde, et la source encore en place est votre seul filet pendant la migration.

Étape 1 : inventorier la source avant de copier

  1. Déclarer MinIO comme alias

    Créez un alias src avec des identifiants qui lisent tous les buckets :
    mc alias set src https://s3.mondomaine.com ACCESS_KEY SECRET_KEY

  2. Compter les objets et la taille

    Pour chaque bucket, notez le nombre d'objets et le volume :
    mc du --recursive src/medias
    mc ls --recursive src/medias | wc -l
    Reportez ces chiffres dans un tableau « avant / après » : c'est votre preuve de fin de migration.

  3. Compter les versions

    Si le versioning est actif, la liste des versions est plus longue que celle des objets :
    mc ls --recursive --versions src/medias | wc -l
    La documentation de mc ls précise que --versions exige un service qui gère le versioning. Un écart important entre les deux comptes dit combien d'historique est en jeu.

  4. Exporter la liste des politiques et des utilisateurs

    Gardez une trace de ce qu'il faudra recréer :
    mc admin policy list src
    mc admin user list src
    Les secrets ne sont pas dans cette sortie et ne peuvent pas l'être : vous les régénérerez.

  5. Relever la configuration des clients

    Dans chaque application qui parle à MinIO, notez l'endpoint, la région, le style d'adressage et la variable d'environnement qui les porte : la bascule ne changera que cela.

Garage et RustFS : les écarts à connaître avant de choisir

Faites défiler le tableau

SujetGarageRustFS
LicenceAGPLv3 (README du dépôt)Apache 2.0 (README du dépôt)
VersioningNon géré : `PutBucketVersioning` et `ListObjectVersions` figurent comme manquantsIndiqué comme disponible dans le README
Politiques de bucket et ACLAucune des deux : un système propre, par clé et par bucketIAM et politiques de bucket ; les ACL sont volontairement non gérées
Accès anonymeRefusé, avec une réponse 403Évalué d'après la politique du bucket
Région du client`s3_region` de `garage.toml`, à reporter dans le client`RUSTFS_REGION`, `us-east-1` par défaut, à reporter dans le client
AdressagePath-style et vhost-style gérésPath-style par défaut, sans configuration DNS
URLs présignéesGéréesGérées, l'hôte, le schéma, le port, la région et le chemin doivent correspondre à la signature
API d'administration MinIOSans objet : on administre avec la commande `garage`Surface séparée : le S3 fonctionne sans que `mc admin` soit garanti

Versioning : ce que la copie perd, et que faire

C'est le point qui décide du choix de la cible. Garage ne gère pas le versioning : sa page de compatibilité S3 le dit sans détour. Si vos buckets conservent un historique que l'application consulte ou que vous devez garder pour des raisons métier, Garage n'en est pas la destination. RustFS indique le versioning comme disponible, mais la copie par rclone sync ou mc mirror n'y recréera pas votre historique.

Trois voies, à choisir bucket par bucket. Assumer la perte : seule la version courante passe, ce qui convient quand le versioning ne servait que de filet contre l'erreur humaine. Copier version par version : vous listez les identifiants avec mc ls --versions, puis vous rejouez les versions de la plus ancienne à la plus récente vers une cible qui gère le versioning, après l'avoir activé sur le bucket ; les dates des versions seront celles de la copie, pas d'origine. Ou archiver l'historique à part, dans un bucket d'archive, et ne migrer que le courant. Dans tous les cas, testez d'abord sur un objet à plusieurs versions.

Étape 2 : préparer la cible, Garage ou RustFS

  1. Garage : assigner puis appliquer le layout

    Aucun bucket n'est utilisable tant que le layout n'est pas appliqué. Relevez l'identifiant du nœud, puis assignez-lui une zone et une capacité :
    garage status
    garage layout assign -z dc1 -c 1G <node_id>
    garage layout apply --version 1
    Ajustez -c à l'espace disque réellement alloué.

  2. Garage : créer la clé, le bucket et les droits

    Les droits se donnent par clé et par bucket :
    garage key create app-key
    garage bucket create medias
    garage bucket allow --read --write --owner medias --key app-key
    Le secret s'affiche à la création de la clé : copiez-le tout de suite dans votre gestionnaire de secrets.

  3. Garage : reporter la région dans le client

    La section [s3_api] de garage.toml définit s3_region. Mettez exactement cette valeur dans la configuration de vos clients, et gardez l'adressage path-style. Une région différente donne des signatures refusées.

  4. RustFS : alias et bucket

    Avec mc configuré sur la cible :
    mc alias set dst http://127.0.0.1:9000 ACCESS_KEY SECRET_KEY
    mc mb dst/medias
    La documentation RustFS recommande des utilisateurs IAM ou des comptes de service plutôt que les clés racine pour les applications.

  5. RustFS : recréer utilisateurs et politiques

    Reprenez la liste exportée à l'étape 1 et recréez chaque utilisateur et chaque politique côté RustFS, avec une clé neuve par application. Alignez ensuite la région : RUSTFS_REGION vaut us-east-1 par défaut, et le client doit utiliser la même.

Étape 3 : copier avec rclone et prouver le résultat

  1. Déclarer les deux remotes

    Utilisez le fournisseur Minio pour la source et Other pour la cible :
    rclone config create src s3 provider=Minio access_key_id=ACCESS_KEY secret_access_key=SECRET_KEY endpoint=https://s3.mondomaine.com
    rclone config create dst s3 provider=Other access_key_id=ACCESS_KEY secret_access_key=SECRET_KEY endpoint=http://127.0.0.1:3900 region=garage
    region=garage suppose s3_region = "garage", la valeur de l'exemple de Garage : mettez la vôtre si elle diffère. Pour RustFS, remplacez l'endpoint par celui de la cible et la région par la valeur de RUSTFS_REGION.

  2. Faire un essai à blanc

    rclone sync modifie la destination pour qu'elle reflète la source, suppressions comprises. Ne l'inversez jamais, et jouez d'abord l'essai :
    rclone sync src:medias dst:medias --checksum --metadata --transfers 16 --dry-run

  3. Lancer la copie à chaud

    MinIO reste en service pendant ce premier passage :
    rclone sync src:medias dst:medias --checksum --metadata --transfers 16 --progress
    --metadata demande à rclone de préserver les métadonnées : contrôlez sur un objet témoin que le type de contenu est arrivé intact.

  4. Vérifier la copie

    Contrôlez que tout ce qui est dans la source existe dans la cible :
    rclone check src:medias dst:medias --one-way --combined /tmp/check-medias.txt
    Le fichier liste chaque chemin avec un symbole : = identique, + absent de la destination, * différent, ! erreur. Zéro ligne +, * ou ! est l'objectif.

  5. Recompter après la copie

    Rejouez mc du --recursive et le décompte d'objets sur la cible, avec l'alias dst, et remplissez la colonne « après » de votre tableau. Les deux chiffres doivent être identiques, sauf écarts expliqués par les versions.

ETag multipart et mc mirror : lire les écarts sans se tromper

L'ETag d'un petit objet envoyé en une seule requête est son MD5, et rclone s'en sert comme somme de contrôle. Pour un objet multipart, la documentation rclone rappelle que l'ETag n'est plus le MD5 des données : c'est le MD5 de la suite des MD5 de chaque partie, suivi du nombre de parties. Il dépend donc de la taille des parties, que le client a choisie à l'envoi.

Votre MinIO a reçu l'objet avec un découpage, rclone le renvoie avec un autre : contenu identique, ETag différent. Un rclone check qui signale ces objets comme différents n'a pas forcément raison. Rejouez-le sur eux avec --download, qui télécharge les deux côtés et compare les données elles-mêmes : plus lent, mais sans ambiguïté. Même vigilance avec mc mirror : sa documentation précise que des sommes composites peuvent différer simplement parce que la répartition en parties a changé.

Si vous préférez rester dans l'écosystème mc, la copie s'écrit avec mc mirror --preserve src/medias dst/medias. L'option --preserve conserve les attributs de la source et ses règles de politique de bucket ; ce dernier point n'a de sens que si la cible sait les lire, ce qui exclut Garage.

Trois limites à connaître. Sans --overwrite, un objet déjà présent sur la cible n'est pas recopié : l'erreur est journalisée et la copie continue, ce qui rend la relance à moitié silencieuse. Avec --remove, les objets de la cible absents de la source sont supprimés, geste à réserver à un bucket que vous maîtrisez. Enfin, mc mirror ne synchronise que l'objet courant, sans version. Sa comparaison porte sur le nom, la taille, la date et la somme de contrôle, sans lire le contenu. Le dépôt de mc est lui aussi archivé : l'outil marche, mais ne bougera plus.

URLs présignées : pourquoi elles tombent à la bascule

Une URL présignée contient une signature calculée avec la clé secrète, l'hôte, la région et le chemin. La documentation RustFS le dit : l'hôte, le schéma, le port, la région et le chemin de la requête doivent correspondre à ceux utilisés pour signer. Changer d'endpoint ou de clé invalide donc tous les liens déjà émis, sans exception, et rien ne les redirige.

C'est une affaire de séquencement. Les liens générés à la volée par votre application se régénèrent dès qu'elle est reconnectée à la cible. Ceux envoyés par e-mail ou stockés en base mourront à la bascule : raccourcissez leur durée de vie quelques jours avant, et prévenez les équipes qui en distribuent à la main.

Étape 4 : basculer en trois temps, sans coupure franche

  1. Sync initial à chaud

    C'est la copie de l'étape 3, jouée pendant que MinIO sert encore le trafic. Elle dure le temps qu'il faut et ne gêne personne. Notez l'heure de fin.

  2. Geler les écritures

    Passez l'application en lecture seule ou en maintenance courte, ou activez une double écriture si votre code la permet. Les lectures peuvent continuer sur MinIO pendant que le sync final tourne.

  3. Sync final avec --update

    Ne transférez que ce qui a changé depuis :
    rclone sync src:medias dst:medias --update --metadata --transfers 16 --progress
    rclone check src:medias dst:medias --one-way
    Recomptez les objets et la taille, et comparez au tableau de l'étape 1.

  4. Changer l'endpoint par variable d'environnement

    Votre application doit lire l'endpoint, la région et les clés dans son environnement, jamais dans le code. Modifiez ces variables, redémarrez le service, puis testez un envoi, une lecture et une suppression sur un objet témoin. Régénérez les liens présignés qui comptent.

  5. Surveiller, puis seulement ensuite démonter

    Laissez MinIO en place, arrêté ou en lecture seule, le temps d'un cycle complet de vos sauvegardes et tâches planifiées. Pointez de nouveau vos sauvegardes restic vers la cible, voir le guide sur les sauvegardes restic.

Le retour arrière tient en une variable

Tant que MinIO n'est pas supprimé et que le dernier sync a été fait en lecture seule, revenir en arrière consiste à remettre l'ancien endpoint dans l'environnement et à redémarrer. Si des écritures ont eu lieu sur la cible depuis la bascule, rapatriez-les d'abord vers la source avec une copie rclone copy dans l'autre sens (jamais un sync, qui supprimerait), puis revenez. N'effacez MinIO qu'après une période d'observation que vous aurez fixée à l'avance.

Dépannage : les symptômes qui reviennent

Un appel sans signature sur Garage répond 403 avec le message Garage does not support anonymous access yet. C'est le comportement attendu de Garage, et la demande d'un accès anonyme figure toujours au suivi du projet comme une fonction jamais priorisée. Si votre application servait des fichiers publics, il faudra des URLs présignées ou un proxy devant le bucket.

Si les écritures sont refusées pour signature invalide après la bascule, comparez la région du client à celle de la cible (s3_region pour Garage, RUSTFS_REGION pour RustFS) et vérifiez que le client utilise l'adressage path-style. Si rclone check signale des objets multipart comme différents alors que leurs tailles sont égales, rejouez-le avec --download. Si une relance de mc mirror ne recopie pas un objet modifié, c'est l'absence de --overwrite. Enfin, si un bucket est vide côté cible alors que le sync a réussi, vérifiez que la clé a bien reçu --read --write sur ce bucket côté Garage ou la bonne politique côté RustFS.

La documentation officielle

Relisez ces sources avant d'agir, ces projets évoluent : le dépôt github.com/minio/minio pour le statut et la licence de MinIO ; github.com/rustfs/rustfs et docs.rustfs.com pour RustFS ; garagehq.deuxfleurs.fr pour la compatibilité S3 de Garage ; rclone.org pour sync et check ; la documentation MinIO de mc mirror. Pour sauvegarder ce stockage, voyez l'article 3-2-1 avec restic et S3.

Un second VPS pour tester la cible avant de couper MinIO

Un second VPS root avec disque NVMe héberge la cible pendant la migration : vous testez à côté de la production et ne coupez MinIO qu'une fois les comptes d'objets validés. La bascule se fait sans toucher à la machine d'origine.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet