Migrating from MinIO to RustFS
MinIO no longer publishes Docker images, so new installs could no longer pull the file storage that TestPlanIt bundled. TestPlanIt's bundled file storage is now RustFS, an open-source (Apache-2.0) S3-compatible server. Attachments, inline images, avatars and project icons all live in this storage.
Do I need to migrate?
| Your setup | What to do |
|---|---|
Docker Compose with the bundled storage (the with-minio profile of docker-compose.prod.yml, or the prod profile of docker-compose.yml) | Follow Docker Compose below. |
Kubernetes with the Helm chart's bundled storage (objectStorage.minio.enabled: true, the default) | Follow Kubernetes (Helm) below. |
| AWS S3 or another external S3-compatible service | Nothing. Your storage is unaffected. |
| A new install | Nothing. New installs use RustFS automatically. |
Docker Compose
Your files stay in ./docker-data/minio. The new storage keeps its files in
./docker-data/rustfs, and a migration script copies everything across and
verifies each file. The old directory is only read, never changed, so it
remains a complete backup.
The steps below use docker-compose.prod.yml with the with-minio profile.
Add the other profiles you normally use (for example --profile with-postgres)
to each docker compose command.
1. Back up your files
cd testplanit
sudo tar -czf minio-backup.tar.gz docker-data/minio
2. Update TestPlanIt
Update your checkout to the new release as you normally do (for example
git pull), then rebuild:
docker compose -f docker-compose.prod.yml --profile with-minio build
3. Run the migration
From the testplanit directory:
./scripts/migrate-minio-to-rustfs.sh
The script stops TestPlanIt, starts the old MinIO storage from the minio/minio
image that is still on your server, copies every bucket into RustFS, and then
compares every file on both sides. It ends with:
Migration complete. Every file was copied and verified.
You can run the script again safely; files that were already copied are skipped.
If you use docker-compose.yml instead, run:
STORAGE_COMPOSE_FILE=docker-compose.yml STORAGE_PROFILE=prod ./scripts/migrate-minio-to-rustfs.sh
If you changed the MinIO root user or password from the defaults, pass them in
LEGACY_MINIO_ROOT_USER and LEGACY_MINIO_ROOT_PASSWORD when running the
script.
4. Start TestPlanIt
docker compose -f docker-compose.prod.yml --profile with-minio up -d
Open a few test cases with attachments and check that images and files load.
5. Remove the old files
Once you have confirmed your files, delete the old storage to free the disk space:
sudo rm -rf docker-data/minio
Keep minio-backup.tar.gz until you are confident everything is in place.
If TestPlanIt does not start after updating
If you start TestPlanIt before migrating, it stops before the app comes up so
that it never looks as if your files were lost. docker compose up reports
that the minio-init service did not complete, and its log explains why:
docker compose -f docker-compose.prod.yml --profile with-minio logs minio-init
ACTION REQUIRED: migrate your files from MinIO to RustFS
Run the migration in step 3, then start TestPlanIt again.
Migrating without the MinIO image
The migration script needs the minio/minio image that your server used
before the update. If that image is no longer on your server, the script says
so and stops. RustFS can serve a copy of the MinIO data directory directly
instead:
docker compose -f docker-compose.prod.yml --profile with-minio stop minio
sudo rm -rf docker-data/rustfs
sudo cp -a docker-data/minio docker-data/rustfs
docker compose -f docker-compose.prod.yml --profile with-minio up -d
This works for the single-drive layout that TestPlanIt's Docker Compose files
created. RustFS adds its own metadata to the copy, so always copy the
directory; never point RustFS at docker-data/minio itself.
Starting without migrating
To start TestPlanIt with an empty storage on purpose, set this in
.env.production (or in your shell for docker-compose.yml):
STORAGE_MIGRATION_SKIP=true
Files uploaded before the update are then missing from TestPlanIt until you migrate them.
Kubernetes (Helm)
The chart keeps the same objectStorage.minio values, Service, Secret keys
and ingress path, and RustFS serves your existing files from the same
persistent volume, so no copy is needed. RustFS writes its own metadata next to
MinIO's, and MinIO cannot read the volume afterwards, so take a snapshot first.
-
Find the storage volume and snapshot it with your storage provider's VolumeSnapshot or backup tool. By default it is named
data-<release>-testplanit-minio-0:kubectl -n <namespace> get pvc | grep minio -
If your values file pins
objectStorage.minio.imageto a MinIO image, remove that line. -
Upgrade the release:
helm upgrade <release> testplanit/testplanit -f my-values.yaml -
Open a few test cases with attachments and check that images and files load.
The storage console
RustFS includes a web console on the same port the MinIO console used (9001
by default, set with DOCKER_MINIO_CONSOLE_PORT). Sign in with the same
access key and secret as before (minioadmin / minioadmin123 unless you
changed them).
Rolling back
Your MinIO files are untouched until you delete them. To go back, check out the
previous TestPlanIt release, which uses ./docker-data/minio again. This only
works while the minio/minio image is still on your server, because it can no
longer be downloaded. On Kubernetes, restore the volume snapshot and the
previous chart release; the cluster needs the MinIO image cached for the same
reason.