Skip to main content
Live. This area is documented as current, user-reliable behavior.

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:admin token for connection administration and assets:write for 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 by connection_id.
  • stackshift_s2: a native S2 destination referenced directly by s2_bucket_id; Assets stores no S2 access key.
  • Connection provider values are aws_s3, r2, wasabi, minio, s3, stackshift_s2, and cloudinary. 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 unique external_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, and AbortMultipartUpload beneath the configured prefix.
  • Bucket scope: ListBucket and ListBucketMultipartUploads, 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 value r2 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, region auto, endpoint https://ACCOUNT_ID.r2.cloudflarestorage.com, static auth, and path-style requests.
  • Wasabi: provider wasabi, the bucket’s Wasabi region, endpoint such as https://s3.us-east-1.wasabisys.com, and static auth.
  • MinIO: provider minio, the deployment’s configured region (commonly us-east-1), a publicly reachable TLS origin such as https://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 in configuration.bucket and any namespace in configuration.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_failed means 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

  • The connection remains failed because list, object tagging, delete, or multipart-abort permission is missing.
  • A generic S3 or MinIO endpoint is rejected because it is not a public HTTPS origin, redirects, or resolves to a private/reserved address.
  • The storage update conflicts because the bucket revision changed; reload the bucket and resubmit with the new revision.
  • Connection or S2 deletion is blocked because an Assets bucket, active migration, upload, relocation, or stored object still references it.

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.