Control a site’s DNS records on install.

DNS management empowers solution providers - such as blogging platforms, email services, and customer management systems - to control customer sites’ traffic and settings.

Cloudflare Apps support all DNS records types (MX, SRV, etc...) defined by Cloudflare’s DNS.

For example, a customer with the website example.com installs an app that inserts a CNAME to point to shops.myservice.com. Now shop.example.com’s DNS will resolve to shops.myservice.com. This means myservice.com controls shop.example.com’s traffic.

install.json with CNAME Record
{
  "resources": [...],
  "hooks": [...],
  "dns": [
    {
      "type": "CNAME",
      "name": "shop",
      "content": "shops.myservice.com"
    }
  ]
}

Declaring Records

To define a customer’s DNS records, declare the records in the app’s install.json file.

Declaring DNS Records on an app follow the same format as Cloudflare’s API for creating a DNS record. All regulations like record limit are managed as they are in the Cloudflare’s standard DNS.

install.json
{
  "resources": [...],
  "hooks": [...],
  "dns": [
   {
     "type": "A",
     "content": "1.2.3.4",
     "name": "sub",
     "ttl": 120,
     "proxied": true
   },
   {
     "type": "MX",
     "name": "example.com",
     "content": "5.5.5.5",
     "priority": 5
   }
   ]
 }

Record Types

All Cloudflare supported DNS record types can be added through an app installation including A, AAAA, SRV, MX etc...

Records Params

The parameters like content, type and proxied are all also defined by Cloudflare’s API for creating a DNS record.

SRV Records
{
  "dns": [
    {
      "type": "SRV",
      "name": "_sip._tcp.example2.com.",
      "content": "SRV 21 1 1 example2.com.",
      "data": {
        "priority": 21,
        "weight": 1,
        "port": 1,
        "target": "example2.com",
        "service": "_sip",
        "proto": "_tcp",
        "name": "example2.com"
      },
      "priority": 21
    }
  ]
}

Install Process

Before the installation is finalized, the customer will receive a confirmation dialog detailing the records your app will create and remove on their domain.

All previously installed DNS records from your app will be removed and replaced on each update to the install. Uninstalling the app removed all records associated with the app.

Please note some records type have specific restraints and will error if multiple records of the same type and name exist.

Dynamic Records via User Input

DNS entries can use a the install options to populate any string value on a record. Use Mustache-style delimiters (e.g. {{value}}) to reference the install option variable.

For example, let’s take user input of subdomain to populate the name and content of a CNAME Record.

Conditional record creation is not currently supported in install options, but can be configured via Webhook.

CNAME using install option
{
  "options": {
    "properties": {
      "subdomain": {
        "title": "Subdomain",
        "type": "string"
      }
    }
  },
  "dns": [
    {
      "type": "CNAME",
      "name": "{{options.subdomain}}",
      "content": "{{options.subdomain}}.myservice.com"
    }
  ]
}

Dynamic Records via WebHooks

Hooks can modify the DNS portion of an install just as hooks can manage any other install option. This allows custom, user specific DNS to be set by your service.

For example, a customer could login into your service via OAuth, then automatically fetch their subdomain from your service.

We generally recommend setting dynamic DNS records in the before-new-install and before-update-install hooks.

install.json with hook
{
  "hooks": [
    {
      "endpoint": "https://mycloudflareworker.com/acme/v2/hook",
      "events": ["before-new-install", "before-update-install"],
      "block": true,
      "authenticate": ["account"],
      "failure": {
        "action": "notify",
        "message": "There was an error communicating with Acme."
      }
    }
  ],
  "options": {
    "properties": {
      "account": {
        "title": "Acme Account",
        "type": "object",
        "format": "account",
        "services": ["acme"],
        "required": true,
        "order": 0
      }
    }
  }
}

You can use a Cloudflare Worker to respond to the hook request. Set the install’s custom DNS and return this in the response.

Cloudflare Worker Hook returns custom DNS
addEventListener('fetch', (event) => {
  return event.respondWith(hookResponse(event.request))
})

aync function fetchCustomerSubdomain(token){
  /* Your service defines logic of the custom subdomain */
  return "somestring"
}

async function hookResponse(request) {
  let reqJSON = await request.json()
  let install = reqJSON.install
  try{
    let token = reqJSON.authentications.account.token.token
    let customSubDomain = await fetchCustomerSubdomain(token)
      install.dns = [
        {
          type: 'CNAME',
          name: customSubDomain,
          content: customSubDomain + '.myservice.com'
        }
      ]
  }catch(err){
    install.dns = [
      {
        type: 'CNAME',
        name: 'default',
        content: 'default.myservice.com'
      }
    ]
  }
  let finalRes = Object.assign({install}, {"proceed": true})
  return new Response(JSON.stringify(finalRes))
}