From another S3-compatible provider

Shorter than the AWS guide, because you have already done the hard part: your code speaks S3 to something that is not Amazon.

What changes, by source

Coming fromAddressingWhat changesWatch for
Cloudflare R2Already path-styleEndpoint and credentials. R2 is signed with region auto; use the real region code here.R2 has no storage classes either, so nothing to unwind. If you were using R2 bindings from a Worker rather than the S3 API, that is an application change, not a configuration one.
Backblaze B2Path or virtual-hostedEndpoint and credentials. The S3-compatible endpoint maps across directly.If you used B2’s native API (b2_upload_file and friends) rather than its S3 endpoint, you are changing APIs, not endpoints — move to an S3 SDK first, against B2, then swap the endpoint.
WasabiVirtual-hosted by defaultEndpoint and credentials; choose path-style or virtual-hosted addressing.Wasabi’s minimum-retention billing means deleting the source early may not save anything — check before you rush the decommission.
DigitalOcean SpacesVirtual-hosted by defaultEndpoint and credentials; choose path-style or virtual-hosted addressing.Spaces bundles a CDN. Ours is not bundled — put a CDN in front of a public bucket and cache on a fixed TTL.
MinIOAlready path-styleEndpoint and credentials, and that is genuinely all.MinIO lets clients create buckets freely; here they come from the dashboard. Anything in your deployment scripts that ran mc mb needs to move.
Google Cloud StorageInterop endpoint, path-styleEndpoint, HMAC credentials, region. If you used the native GCS client rather than the interop endpoint, this is an SDK change.GCS object metadata and ACL semantics do not map one to one. Copy with a tool that moves content type and user metadata explicitly, and re-check both after.

The two that apply to all of them

Whatever you are coming from, these are the differences most likely to surface. If your current provider supports bucket-level configuration through the S3 API — and most do — that is the part of your setup that needs rethinking, not your data path.

You’ll see
405 MethodNotAllowed on PutBucketPolicy, PutBucketLifecycleConfiguration, PutBucketWebsite, PutBucketReplication, PutBucketNotificationConfiguration, PutBucketTagging, PutPublicAccessBlock and their delete counterparts; the matching Get calls return 501 or are refused upstream.
Why
These configure infrastructure behaviour that PopCloud manages itself. Access control is expressed through credential scopes and the bucket's public flag rather than through bucket policies.
Instead
Use credential scopes for access control (permissions plus a bucket allowlist, optionally with an expiry), the bucket's public flag for anonymous reads, and the control plane for CORS. Tools that reconcile bucket configuration — Terraform's `aws_s3_bucket` in particular — must be limited to object-level resources.

Then follow the same steps

Provisioning, copying, cutting over and verifying are identical regardless of source. The AWS guide covers all four, and copying your data covers the transfer itself — including copying directly between two providers without a local round trip.