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"
}
]
}
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
}
]
}
All Cloudflare supported DNS record types
can be added through an app installation including A
, AAAA
, SRV
, MX
etc...
The parameters like content
, type
and proxied
are all also defined by Cloudflare’s API for creating a DNS record.
{
"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
}
]
}
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.
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.
{
"options": {
"properties": {
"subdomain": {
"title": "Subdomain",
"type": "string"
}
}
},
"dns": [
{
"type": "CNAME",
"name": "{{options.subdomain}}",
"content": "{{options.subdomain}}.myservice.com"
}
]
}
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.
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))
}