# colis with Cloudflare R2

> Deliver files to your clients from a Cloudflare R2 bucket with colis: the createBucket() configuration, the CLI starter, and what to know about this provider.

Canonical: https://colis-site.vercel.app/en/providers/cloudflare-r2 · Markdown: https://colis-site.vercel.app/en/providers/cloudflare-r2.md · Français: https://colis-site.vercel.app/providers/cloudflare-r2

S3-compatible, the region is always "auto", and the dashboard takes the CORS rule as JSON.

**createBucket()**
```ts
import { createBucket } from '@colis/core'

const store = createBucket({
  bucket: 'transfers',
  endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID!,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
  },
  publicUrl: 'https://cdn.example.com', // optional: your R2 custom domain
})
```

## Why this one
R2 speaks the S3 API and ignores the region. It is the provider the delivery page’s README is written against: a bucket, an API token scoped to it, five environment variables, and a CORS rule for large files, pasted under the bucket’s settings.

## A starter configuration, and what is left to do.
init writes the file with ${VAR} references rather than secrets, so it is meant to be committed; the env file it points at is not.

```sh
colis init --provider r2 --bucket transfers
```
**colis.config.json**
```json
{
  "bucket": "transfers",
  "region": "auto",
  "endpoint": "https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com",
  "prefix": "transfers",
  "expiresIn": "24h",
  "envFile": ".env",
  "credentials": {
    "accessKeyId": "${R2_ACCESS_KEY_ID}",
    "secretAccessKey": "${R2_SECRET_ACCESS_KEY}"
  }
}
```

### Then
1. Put R2_ACCOUNT_ID, R2_ACCESS_KEY_ID and R2_SECRET_ACCESS_KEY in .env, and keep it out of git.
2. The API token needs Object Read & Write on this bucket, and nothing else.
3. Add a lifecycle rule that deletes objects under the prefix after a day or two.
4. Run `colis verifier`. It performs the operations colis needs and reports what happened.

## Notes on R2.
- **region: "auto"** — R2 ignores the region and the SDK insists on one. Setting an endpoint makes colis default to "auto", so there is nothing to write.
- **Large files** — Large files go from the browser straight to the bucket, in parts. The bucket needs a CORS rule that allows PUT from your delivery page and exposes ETag; without it, small files still work.
- **Expiry cleanup** — The expiry stops a parcel being handed over; only a lifecycle rule deletes the object. Give the prefix a rule that expires objects after a day or two, and colis verifier turns green.

[The full guide](https://colis-docs.vercel.app/docs/stockages#cloudflare-r2)
