How to Serve WordPress Images from a Custom Domain on R2
To serve WordPress images from your own domain on Cloudflare R2, open your bucket's settings, add a custom domain such as media.yoursite.com, wait for it to activate, then set that address as your media address in your offload plugin. The domain must be a zone on the same Cloudflare account as the bucket.
Why not just use r2.dev?
Cloudflare's r2.dev address is meant for testing. It's rate-limited and not cached, so it isn't suited to a live site. A custom domain also means your image addresses stay yours, even if you change something later.
What do you need?
- A domain whose DNS is on the same Cloudflare account as the bucket. It doesn't need to be the domain your site runs on, as long as it's a zone on that account.
- A subdomain to use for media.
If your domain's DNS is elsewhere, you'll need to add it to that Cloudflare account first.
How do you connect it?
- In the Cloudflare dashboard, open R2, then your bucket, then Settings.
- Under Custom Domains, add
media.yoursite.com. - Confirm. Cloudflare creates the DNS record and the certificate.
- Wait until it shows as active. This can take a few minutes.
How do you check it?
Upload a test file to the bucket, then open its address on your domain, like https://media.yoursite.com/test.png.
If you use Offloft, enter the domain in Settings → Delivery and run the delivery check. It loads a small test image from there, and images switch only after that succeeds. If it doesn't, your images keep loading from your server, and the message tells you what to look at.
What about caching?
Files served through a custom domain can use Cloudflare's cache, so repeat requests may not need to reach the bucket. Keep long cache lifetimes for images, and change the address when a file changes. Offloft does that by default with versioned file paths.
What if you use Cloudflare's other image features?
Test them with your media domain. If something changes images on the way through, the delivery check may report that a different file came back.