Skip to content

S3 Migration

The S3 Migration tool copies a bucket — or a single prefix inside one — from any S3-compatible source into your Carolina Cloud bucket. The copy runs entirely on our infrastructure: you fill out a short form, hit Start migration, and close the tab. We’ll keep going overnight, across reconnects, and through the multi-terabyte mark without you doing anything else.

Dashboard sidebar → Storage → Migrate.

  • Anything S3-compatible. AWS S3, Wasabi, Backblaze B2, Cloudflare R2, DigitalOcean Spaces, MinIO, self-hosted Ceph — if it speaks the S3 API, the tool can read from it.
  • A whole bucket or a single prefix. Leave the source Prefix blank to copy the whole bucket. Set it to a folder (e.g. experiments/2025/) to copy just that subtree. Set it to a single object key (e.g. report.pdf) to copy one file.
  • Up to one job at a time per account. The tool runs your migration on a dedicated worker; queueing a second one while the first is live returns a 409.
  • Objects in AWS Glacier / Deep Archive. Glacier objects need to be restored to standard S3 before they’re readable, and the tool doesn’t yet issue restore requests for you. If you try to migrate a bucket with Glacier objects mixed in, the copy will fail with Object in GLACIER, restore first. For now: restore the objects via the AWS Console or aws s3api restore-object, wait for the restore window to open, then start the migration. First-class Glacier source support is on the roadmap.
  • Sources that aren’t S3-compatible. Google Cloud Storage’s native API, Azure Blob, and FTP/SFTP sources are not supported. (GCS has an S3 interop mode that does work; you’d use it via the custom-endpoint option.). FTP/SFTP sources will soon be available to migrate to a Carolina Cloud bucket.

The Provider dropdown has presets for the common cases — AWS S3 (eight regions), Wasabi (two regions), Backblaze B2. Pick the one that matches where your data lives now. Each preset fills in the endpoint URL and the region automatically.

If your source isn’t in the list, choose Custom endpoint… and fill in:

  • Endpoint URL — e.g. https://<accountid>.r2.cloudflarestorage.com for Cloudflare R2, https://nyc3.digitaloceanspaces.com for DigitalOcean Spaces, or your MinIO/Ceph hostname.
  • Region (optional) — required for AWS, Wasabi, Backblaze B2, and DigitalOcean Spaces, all of which sign requests with SigV4 and reject signatures from the wrong region. Leave blank for Cloudflare R2, MinIO, or anything else that accepts us-east-1 by default.
  • Access key and Secret key — a pair of S3 credentials with at least s3:ListBucket and s3:GetObject on the source bucket. Read-only is sufficient.
  • Bucket — the source bucket name.
  • Prefix (optional) — a folder (photos/) or a single object key (report.pdf). Leave blank to copy the whole bucket.

The secret key is forwarded once to the worker that runs rclone copy, then discarded. It’s never written to the database, and the worker wipes its on-disk config when the job finishes.

  • Bucket — the Carolina Cloud bucket the files will land in. If you belong to an org with a provisioned bucket and you’re an admin or the org owner, both your personal bucket and the org bucket appear in the dropdown. See Who can migrate to the org bucket below.
  • Prefix (optional) — auto-mirrors whatever you typed for the source prefix until you edit it. Files land at <prefix>/... inside the destination bucket.

Click Start migration. The button shows Validating source credentials… for a beat while we run a one-object preflight list against the source — this catches bad credentials, the wrong endpoint, a missing bucket, or an empty bucket/prefix before any worker is even involved.

If the preflight passes, the page swaps into the active-job view.

The active-job card shows:

  • Elapsed time — ticks live, second by second.
  • Progress bar and percentage — based on bytes copied vs. the source bucket’s total size. The first sizing pass can take a minute or two on a large bucket; until it finishes, the bar is indeterminate and the label reads Calculating total size…
  • Data copied — bytes moved out of total bytes.
  • Files copied — file count moved out of total files.
  • Recent activity — collapsible tail of the worker’s log, refreshing every 30 seconds.

You can close the tab. The migration keeps running. When you come back to the page later (even days later), it remembers your last-viewed job and picks back up where it left off.

Hit Cancel migration to stop a job mid-flight. Anything already copied stays in your destination bucket — cancellation does not undo partial transfers.

You’ll land on one of three terminal cards:

  • Migration complete — green check. Shows total bytes/files copied and the wall-clock duration. Files are in your destination bucket and ready to use.
  • Migration failed — red X. Shows the worker’s error message and exit code, plus the tail of the log so you can see what went wrong. Common causes: a transient source-side network error, a source object in Glacier, or a permission change on the source IAM key mid-job.
  • Migration cancelled — neutral. Confirms how many bytes/files made it through before you hit cancel.

All three give you a Start another migration button to launch a fresh job.

ErrorWhat it meansFix
Source credentials rejected — InvalidAccessKeyIdThe source provider doesn’t recognize the access key.Most often a provider mismatch (e.g. AWS preset with Wasabi keys). Check the preset, then check for typos/whitespace.
Source credentials rejected — SignatureDoesNotMatchAccess key recognized; secret didn’t match.Re-paste the secret. Make sure access key and secret are a matching pair.
Source credentials rejected — AccessDeniedCredentials valid but IAM policy doesn’t allow listing the bucket.Grant s3:ListBucket and s3:GetObject on the source bucket to the IAM user.
Source bucket not foundNo bucket by that name lives at that endpoint.Check spelling. For AWS, make sure you’ve selected the bucket’s actual region.
No objects found at source bucket/prefixThe bucket and credentials work, but the prefix is empty.Either pick a different prefix or leave it blank to copy the whole bucket.
AuthorizationHeaderMalformed — region ‘X’ is wrong; expecting ‘Y’The endpoint URL points at one AWS region but you signed for another.Pick the matching AWS preset, or set the Region field under the custom endpoint option.
Object in GLACIER, restore firstOne or more objects in the prefix are in Glacier / Deep Archive and aren’t readable until restored.Issue a restore via the AWS Console or aws s3api restore-object, wait for it to complete (3–48h depending on tier), then re-run the migration.
You already have a migration in progressA previous job is still active on your account.Wait for it to finish, or cancel it.

Each migration runs with a fixed per-job bandwidth cap. That’s a deliberate ceiling so a single migration can’t starve other customer workloads sharing the worker. A 1 TiB bucket typically finishes in roughly 1.5 hours of wall-clock time, network and source-side throttling permitting. Bigger transfers (10 TiB+) are perfectly fine to leave running overnight or over the weekend. If you require an expediated transfer, please contact support@carolinacloud.io.

  • Source secrets are never persisted. They’re passed through to the worker for the duration of the job, then wiped from disk.
  • The destination is always your Carolina Cloud bucket. Carolina Cloud does not migrate data into a third-party destination; the destination dropdown is restricted to the buckets you own or admin.
  • The copy is server-to-server. Bytes flow directly from your source to Wasabi over the worker — they don’t traverse your laptop, and they don’t pass through your local internet connection.

If your account is in an org and the org has a bucket provisioned, both your personal bucket and the org bucket show up in the destination dropdown. Only org admins (the owner and anyone the owner has promoted) can actually dispatch a migration into the org bucket. A regular member who picks the org bucket from the dropdown will get a 403 from the dispatch endpoint.

Members can always migrate into their own personal bucket — no admin role required.

See Organizations → Overview for the full breakdown of org roles.