Bring your own bucket

Bring your own bucket

Point a workspace at storage you already pay for, instead of the shared bucket.

In preview. Bring-your-own-bucket is available to a small set of workspaces while we finish testing. If your workspace doesn't show "Connect your own bucket" on its settings page, it isn't in the preview yet.

Set up your bucket #

A workspace admin runs the connect wizard from the workspace settings page. Three steps on the Cloudflare dashboard, then verify before anything is saved.

1. Create an R2 bucket

Dashboard → R2Create bucket. Any name that follows Cloudflare's rules works (3–63 characters; lowercase letters, digits, hyphens). If the bucket is in a jurisdiction (eu or fedramp), pick that same jurisdiction in the wizard.

2. Create a bucket-scoped API token

R2Manage API TokensCreate API Token, permission Object Read & Write, scoped to that one bucket. You get an Access Key ID, a Secret Access Key, and your account ID.

Scope the token to one bucket, not the whole account. uploads.sh encrypts the key pair, but a bucket-scoped token still limits the blast radius if anything goes wrong.

3. Optional: custom domain for public reads

Bucket → SettingsPublic accessCustom Domains, connect a domain on a Cloudflare zone in your account, then paste the URL (for example https://media.example.com) into the wizard as the public base URL. See the serving matrix below for what this buys you.

Enter the account ID, bucket name, and key pair, then run verify. It checks the inputs, authenticates against the bucket, round-trips a test object, and (on first attach) confirms the bucket is empty unless you choose to adopt existing contents. Only a passing verify can save.

You can only connect at workspace creation or on an empty workspace — there's no migration path yet for workspaces that already have files (every published URL would break). File-size and video-size limits still apply on a BYO bucket; the storage-quota budget does not.

Serving: custom domain vs signed-only #

Public accessHow files are servedTrade-off
Custom domainDirect public URL under your domain.Recommended — needs a domain on a Cloudflare zone in your account.
No public URLSigned URLs, generated on demand.Fine for viewing; GitHub embeds won't render (see below).
r2.dev managed URLNot supported. The wizard rejects r2.dev base URLs — connect a custom domain, or save without a public URL for signed-only access.

What's different #

  • GitHub embeds. Shared-bucket images get an embed host that GitHub's Camo proxy revalidates after overwrite. That twin doesn't extend to a custom domain, so a BYO image without a public URL (signed-only) won't render inline in a GitHub comment. The file still uploads and still has a share page.
  • retentionDays auto-cleanup. Age-based retention walks a prefix on the shared bucket. A BYO bucket has no shared prefix, so automatic retention isn't available — delete old files yourself if you need that.
  • Storage quota. On a BYO bucket the plan's storage budget doesn't apply (you pay Cloudflare for the bucket). File-size and video-size upload limits still do.

Data ownership & disconnecting #

The bucket and everything in it are yours. uploads.sh stores only encrypted credentials and a pointer to the bucket — never a copy of your files.

Disconnecting never touches your objects. It removes the stored credentials and points the workspace back at the shared bucket. Your bucket stays as it was. Connecting again is a fresh attach, same as the first time.