Why this migration is required
Formbricks 4.0 uses an S3‑compatible object store for all file uploads. For One‑Click installs that previously stored files locally (named volumeuploads
or a host bind like ./uploads
), you must migrate those files to MinIO.
This guide shows a safe, idempotent migration using the script docker/migrate-to-minio.sh
included in this repository.
This migration script is supported on Ubuntu only (Ubuntu 20.04+), requiring Bash 4+ and GNU sed/grep.
Prerequisites
- DNS: a subdomain for object storage, e.g.
files.<your-domain>
pointing to your server IP - Your One‑Click installation directory (contains
docker-compose.yml
) - Docker/Compose installed and working
What the script does
- Adds MinIO services (
minio
,minio-init
) and S3 env vars todocker-compose.yml
- Asks to restart your Compose stack (you should say Yes)
- Detects your existing upload sources post‑start and migrates them to MinIO
- Host bind mounts (e.g.,
./uploads
) - Named volume target in the container (legacy:
/home/nextjs/apps/web/uploads
or custom target) - Absolute
UPLOADS_DIR
in the container if set
- Host bind mounts (e.g.,
- Cleans up
docker-compose.yml
after success: removesUPLOADS_DIR
, removes alluploads
volume mappings and the rootuploads:
definition - Optionally restarts again to apply the cleanup
Run the migration
From the directory that contains yourdocker-compose.yml
:
Verifying the migration
- Check the UI: previously uploaded images/logos/files should load
- List bucket contents with
mc
(reuses minio‑init service env):
- Confirm
docker-compose.yml
no longer containsUPLOADS_DIR
oruploads:
volume mappings (post‑cleanup)
Notes on sources
- The script migrates from multiple sources, in order:
- Host bind (absolute path resolved by
docker compose config
) - Container mount target for named volume
uploads
(e.g.,/home/nextjs/apps/web/uploads
or your custom.../files/uploads
) - Absolute
UPLOADS_DIR
(container path)
- Host bind (absolute path resolved by
- The relative path/key structure is preserved:
${environmentId}/${accessType}/fileName.ext
- Re‑runs copy only new/changed files (idempotent)
Troubleshooting
-
MinIO 404 on file URLs
- If you use virtual‑hosted style (
bucket.files.domain
), ensure Traefik router rule includes wildcard:
- If you use virtual‑hosted style (
-
InvalidAccessKeyId in UI
- Happens if keys rotated between runs. Re‑run the script; it reuses S3_* credentials and reattaches policy.
-
Undefined volume
minio-data
- Re‑run; the script ensures
minio-data
exists in the rootvolumes:
block.
- Re‑run; the script ensures
-
List bucket contents
Rollback
- Your original
docker-compose.yml
is backed up asdocker-compose.yml.backup.<timestamp>
- To revert, restore the backup and restart Compose: