# Connect Cloudflare R2 to WordPress

To offload WordPress media to Cloudflare R2, install Offloft, create an R2 bucket and an API token limited to that bucket, then connect your own domain so visitors can load files. Offloft tests the connection and public delivery before it serves anything from the cloud.

## 1. Create the bucket

In the Cloudflare dashboard, go to **Storage & databases > R2 > Overview** and select **Create bucket**.

**Name:** lowercase letters, numbers and hyphens, 3 to 63 characters, not starting or ending with a hyphen.

**Location:** leave it on **Automatic**, or pick the region closest to most of your visitors.

Choose **Specify jurisdiction** only if your files must stay in the European Union, FedRAMP or United States jurisdiction. *It cannot be changed later, and you must pick the same jurisdiction in Offloft.*

Bucket name:

```
my-site-media
```

## 2. Create an API token for Offloft

On the R2 Overview page, under **Account Details**, select **Manage** next to **API Tokens**.

Select **Create Account API token**. An account token keeps working if the person who made it leaves your Cloudflare account; a User API token does not.

**Permissions:** choose **Object Read & Write**. Offloft never needs Admin permissions.

Under **Specify bucket(s)**, choose **Apply to specific buckets only** and pick "my-site-media", so the token cannot touch your other buckets.

Select **Create API Token**. Copy the **Access Key ID** and the **Secret Access Key** into Offloft together with your account ID. *Cloudflare shows the secret only once.*

Account ID:

```
your-account-id
```

S3 endpoint (Offloft fills this in for you):

```
https://your-account-id.r2.cloudflarestorage.com
```

## 3. Connect your own domain

R2 buckets are private until you connect a domain. Open the bucket, go to **Settings > Custom Domains** and select **Add**.

Enter media.yoursite.com, select **Continue**, then **Connect Domain**. The domain must be a zone in this same Cloudflare account.

Wait until the status changes from **Initializing** to **Active**, usually a few minutes.

In Offloft, use https://media.yoursite.com as the delivery address.

Domain:

```
media.yoursite.com
```

Delivery address:

```
https://media.yoursite.com
```

## 4. Or: turn on the r2.dev address for testing (optional)

Without a domain you can try things out with Cloudflare's r2.dev address. *It is rate-limited and not cached, so do not use it for a live site.*

Open the bucket, go to **Settings > Public Development URL** and select **Enable**. Type "allow" to confirm.

Copy the address it shows (https://pub-….r2.dev) into Offloft as the delivery address.

## 5. Allow your site to read files (CORS) (optional)

This step is optional. Images on your pages load without it. You need it only when your site's own scripts read files from storage, for example image editors, web fonts or 3D viewers. The rule below lets only your site read files, and only read them.

Open the bucket, go to **Settings > CORS Policy**, select **Add CORS policy**, choose the **JSON** tab and paste the rule.

CORS policy:

```json
[
  {
    "AllowedOrigins": ["https://yoursite.com"],
    "AllowedMethods": ["GET", "HEAD"],
    "AllowedHeaders": ["*"],
    "MaxAgeSeconds": 3600
  }
]
```

## 6. Check Cloudflare rules on your domain (optional)

Your domain runs through Cloudflare, so its rules apply to your files too. If the delivery check says files come back changed or with the wrong type, look at the rules on the zone for media.yoursite.com:

**Rules > Overview** (Transform Rules, Cache Rules, Redirect Rules), **Workers routes**, and **Speed** settings that rewrite content.

A cache rule that caches everything on media.yoursite.com is fine and makes files faster.

## Permissions Offloft needs

An Account API token with Object Read & Write, applied to this bucket only. Offloft never needs Admin permissions.

## Serving your files

R2 buckets are private until you connect a domain. Use your own domain, which must be a zone in the same Cloudflare account. Cloudflare's r2.dev address is for testing only: it is rate-limited and not cached. The delivery check loads a small test image from whichever address you enter.

## Questions

### Should I use a custom domain or the r2.dev address?

A custom domain for a live site. Cloudflare's r2.dev address is rate-limited and not cached, so keep it for testing.

### Which kind of API token should I create?

An Account API token. It keeps working if the person who made it leaves your Cloudflare account; a User API token does not.

### What if I chose a jurisdiction for my bucket?

Pick the same jurisdiction in Offloft. A jurisdiction cannot be changed after the bucket is created.

### Do I need the CORS step?

Only when your site's own scripts read files from storage, for example image editors, web fonts or 3D viewers. Images on your pages load without it.

Source: https://www.offloft.com/setup/cloudflare-r2
