Skip to content
On this page

Mapping a custom domain to Cloudflare R2 bucket using API

Map a custom domain to a cloudflare r2 bucket. This also requires adding a policy.

API key requires permissions

account -> workers r2 storage -> edit
zone -> dns -> edit

Using curl here(because I was trying out zx), but fetch should be used if in js.

See also - Setting CORS settings for Cloudflare R2 bucket using API

typescript
import { $ } from 'zx'

const $$ = $({
    verbose: true,
    env: {
        // NODE_ENV: 'production'
    },
})

const bucket = 'test-bucket'
const accountId = 'xxxxx'

// const zone = await cloudflare.zones.get({
//     zone_id: 'xxxxx',
// })
const zoneName = zone.name
const zoneId = zone.id
const domain = 'assets.example.com'

const cdUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucket}/custom_domains`
const cdFlags = [
    '-H', 'accept: */*',
    '-H', 'accept-language: en-US,en;q=0.9',
    '-H', 'cache-control: no-cache',
    '-H', 'content-type: application/json',
    '-X', 'POST',
    '-H', 'Authorization: Bearer ' + process.env['CLOUDFLARE_API_TOKEN'],
    '--data-raw', `{"domain":"${domain}","zoneId":"${zoneId}","zoneName":"${zoneName}"}`,
    '--compressed',
    '-X', 'POST'
]
const cdUpdate = JSON.parse((await $$`curl ${cdUrl} ${cdFlags}`.catch(e => {
    console.error(e.message)
    console.error('-------------------------------------------')
    console.error(`UNKNOWN ERROR - Failed to map custom domain - check if it already exists - ${domain}`)
    return {stdout: '{}'}
})).stdout)
if(!cdUpdate.success) {
    console.error('-------------------------------------------')
    console.error('\n')
    console.error('Failed to update Custom Domain DNS mapping')
    console.error('This must be done manually')
    console.error(`Here - https://dash.cloudflare.com/${accountId}/r2/default/buckets/${bucket}/settings`)
    console.error('Add custom domain - ' + domain)
    console.error('\n')
    console.error('-------------------------------------------')
}

const cdPolicyUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/r2/buckets/${bucket}/policy?cname=${domain}&access=CnamesOnly`
const cdPolicyFlags = [
    '-H', 'accept: */*',
    '-H', 'accept-language: en-US,en;q=0.9',
    '-H', 'content-length: 0',
    '-X', 'PUT',
    '-H', 'Authorization: Bearer ' + process.env['CLOUDFLARE_API_TOKEN'],
]
const cdPolicyUpdate = JSON.parse((await $$`curl ${cdPolicyUrl} ${cdPolicyFlags}`.catch(e => {
    console.error(e.message)
    console.error('-------------------------------------------')
    console.error(`UNKNOWN ERROR - Failed to add custom domain policy - check if it already exists - ${domain}`)
    return {stdout: '{}'}
})).stdout)
if(!cdPolicyUpdate.success) {
    console.error('-------------------------------------------')
    console.error('\n')
    console.error('Failed to add Custom Domain DNS mapping policy')
    console.error('This must be done manually')
    console.error(`Here - https://dash.cloudflare.com/${accountId}/r2/default/buckets/${bucket}/settings`)
    console.error('Remove and Add custom domain - ' + domain)
    console.error('\n')
    console.error('-------------------------------------------')
}

Made with ❤️ using the awesome vitepress