Goal
Put new Assets objects and derivatives in the selected customer-owned backend, verify access safely, and relocate historical objects without an availability gap.Prerequisites
- An Assets bucket and its current revision
- An
assets:admintoken for connection administration andassets:writefor bucket storage changes - Bucket and prefix permissions at the external provider, or an owned StackShift S2 bucket
Workflow
1
Create a provider connection. Prefer AWS AssumeRole; use static credentials only when the provider cannot issue a role.
2
For AWS, install the returned trust and permission policies with the connection external ID. For S2, select or create an owned bucket without creating an access key.
3
Verify the connection. StackShift probes the reserved verification prefix and records either
verified or a redacted failure.4
Update the Assets bucket storage configuration with its current revision. New originals, versions, derivatives, and video outputs use the new backend immediately.
5
Run a relocation dry run, then execute relocation if historical objects must move. Existing objects remain on their recorded backend until each verified cutover commits.
Storage modes and provider identifiers
managed: the default for existing and new Assets buckets unless you explicitly select another mode.byob: an external S3-compatible destination referenced byconnection_id.stackshift_s2: a native S2 destination referenced directly bys2_bucket_id; Assets stores no S2 access key.- Connection provider values are
aws_s3,r2,wasabi,minio,s3,stackshift_s2, andcloudinary. Cloudinary is an import source only and cannot be a bucket destination. - R2, Wasabi, MinIO, and generic S3 require explicit static credentials and a public HTTPS endpoint. Endpoint-backed providers use path-style requests.
AWS AssumeRole connection
Create the connection first. Its response includes a uniqueexternal_id, trust_policy, and prefix-scoped permission_policy. Install those returned policies in the customer AWS account, then verify the connection. The role session is short-lived and names the connection; no static key is stored.
Required external permissions and verification
- Object scope:
GetObject,PutObject,GetObjectTagging,DeleteObject, andAbortMultipartUploadbeneath the configured prefix. - Bucket scope:
ListBucketandListBucketMultipartUploads, constrained to the configured prefix. - Verification performs list, write, read, metadata/head plus tags, delete, multipart-create/upload, and multipart-abort beneath
.stackshift-assets-verification. - The probe always attempts cleanup. A cleanup failure is part of the verification failure and should be resolved before production writes.
- Stored credentials are envelope-encrypted with connection-specific authenticated data. Create and update responses never return the secret payload.
Static S3-compatible connection
Use the API provider valuer2 for Cloudflare R2. Keep the access key in the credentials object, never in configuration. Updating credentials replaces the encrypted secret; listing or getting the connection returns only non-secret configuration and verification state.
Provider endpoint settings
- Cloudflare R2: provider
r2, regionauto, endpointhttps://ACCOUNT_ID.r2.cloudflarestorage.com, static auth, and path-style requests. - Wasabi: provider
wasabi, the bucket’s Wasabi region, endpoint such ashttps://s3.us-east-1.wasabisys.com, and static auth. - MinIO: provider
minio, the deployment’s configured region (commonlyus-east-1), a publicly reachable TLS origin such ashttps://objects.example.com, and static auth. - Generic S3: provider
s3, the provider’s region and public HTTPS origin, static auth, and path-style requests. - AWS static fallback: provider
aws_s3,auth_type: static, standard AWS region, no custom endpoint, and a narrowly scoped access key. AssumeRole remains preferred. - Do not include a bucket path in
endpoint; put the bucket inconfiguration.bucketand any namespace inconfiguration.prefix.
Native StackShift S2
List or create an owned S2 bucket through the Assets storage client, then attach its UUID. Ownership is checked against the Assets workspace. Internally, Assets uses a bucket-and-prefix-scoped S2 principal with put, get, list, delete, and multipart operations. S2 quotas, checksums, encryption, lifecycle, versioning, and conformance remain enforced by the Object Store service.Cutover, relocation, deletion, and billing
- A storage configuration change affects new writes immediately. Historical originals, versions, derivatives, and video outputs keep their own backend reference.
- Relocation streams to the destination, verifies SHA-256, and atomically changes the durable reference. If transfer or verification fails, reads continue from the source.
- Source deletion happens after commit.
source_delete_failedmeans delivery already uses the destination; remove the old object after restoring provider access instead of rolling back the reference. - All backends count toward logical Assets quotas and processing, OCR, and CDN usage. External BYOB and native S2 objects do not accrue Assets managed-storage byte-hours; S2 has its own Object Store accounting.
- External bucket endpoints and credentials never appear in asset URLs. CDN/origin routing resolves each object’s recorded backend server-side.
Expected result
The Assets bucket writes through the selected backend while all public and private delivery continues through the StackShift CDN gateway.
Common failures
Related guides
Cloudinary, S3, R2, and S2 migrations
Inventory, dry-run, import, deduplicate, retry, cancel, and report durable migrations from Cloudinary or S3-compatible storage into StackShift Assets.
Assets platform API, SDK, CLI, and operations
A complete interface and recovery reference for storage connections, S2, imports, relocation, OCR, browser capabilities, reports, scopes, events, billing, and durable worker behavior.
Access keys, encryption, isolation, and quotas
Operate S2 credentials, encryption, visibility, tenant isolation, request limits, and customer-plan quotas safely.