If you use Netlify to manage your DNS, you can use their API to programtically add, remove or update records.
For me, the use case is that I run a home server and I want to be able to dynamically map my IP address to a domain. This is also known as Dynamic DNS and there are many providers out there that offer this service such as Afraid FreeDNS and No-IP.
Having used some of those services in the past, I realised that I didn't really need them and could write a small script to do this myself.
As my ISP issues dynamic IP addresses, I use the following code inside a Docker container to insert (or update if it exists) an A record to ensure the domain always resolves to the correct IP.
This guide however, will only concentrate on using the Netlify API with JavaScript and no dependencies!
fetch
.cd
into it.mkdir dns-updater
cd $_
.env
file and use a package like dotenv
to retrieve it but for the purpose of this guide, we're not going to.)export ACCESS_TOKEN=MY_PERSONAL_ACCESS_TOKEN
.nvmrc
to ensure we're using the correct Node version.echo '18' > .nvmrc
fnm use
If you haven't tried FNM as a drop-in
replacement for nvm
, I highly recommend it. After countless hours of trying
to speed up my terminal with nvm
, I came across this and have never looked
back.
echo '#!/usr/bin/env node' > index.js
code index.js
const ACCESS_TOKEN = process.env.ACCESS_TOKEN
if (!ACCESS_TOKEN) {
throw new Error('Please set the ACCESS_TOKEN environment variable')
}
const ipValue = '8.8.8.8' // the value of the DNS record
const domainName = 'mydomain.com'
const host = 'www'
const zoneId = domainName.replace('.', '_') // replace any dots in your domain with an underscore
const baseUrl = `https://api.netlify.com/api/v1/dns_zones/${zoneId}/dns_records`
const headers = {
'Content-type': 'application/json',
Authorization: `Bearer ${ACCESS_TOKEN}`,
'User-Agent': 'DNS Updater',
}
const getExistingRecordIfExists = async hostname => {
const records = await fetch(baseUrl, {
method: 'GET',
headers,
}).then(response => response.json())
return records.find?.(record => record.hostname === hostname)?.id
}
const updateDns = async () => {
const fullHost = `${host}.${domainName}`
console.log(`Setting A record for: ${fullHost}`)
const id = await getExistingRecordIfExists(fullHost)
if (id) {
console.log(`${fullHost} exists. Deleting first...`)
await fetch(`${baseUrl}/${id}`, {
method: 'DELETE',
headers,
})
}
const {
type,
hostname: savedHostname,
value: savedValue,
errors,
} = await fetch(baseUrl, {
method: 'POST',
headers,
body: JSON.stringify({
type: 'A',
hostname: host,
value: ipValue,
}),
}).then(response => response.json())
if (errors.length) {
throw new Error(JSON.stringify(errors))
}
console.log(`Record ${type} created for ${savedHostname}: ${savedValue}`)
}
updateDns()
#!/usr/bin/env node
const ACCESS_TOKEN = process.env.ACCESS_TOKEN
if (!ACCESS_TOKEN) {
throw new Error('Please set the ACCESS_TOKEN environment variable')
}
const ipValue = '8.8.8.8' // the value of the DNS record
const domainName = 'mydomain.com'
const host = 'www'
const zoneId = domainName.replace('.', '_') // replace any dots in your domain with an underscore
const baseUrl = `https://api.netlify.com/api/v1/dns_zones/${zoneId}/dns_records`
const headers = {
'Content-type': 'application/json',
Authorization: `Bearer ${ACCESS_TOKEN}`,
'User-Agent': 'DNS Updater',
}
const getExistingRecordIfExists = async hostname => {
const records = await fetch(baseUrl, {
method: 'GET',
headers,
}).then(response => response.json())
return records.find?.(record => record.hostname === hostname)?.id
}
const updateDns = async () => {
const fullHost = `${host}.${domainName}`
console.log(`Setting A record for: ${fullHost}`)
const id = await getExistingRecordIfExists(fullHost)
if (id) {
console.log(`${fullHost} exists. Deleting first...`)
await fetch(`${baseUrl}/${id}`, {
method: 'DELETE',
headers,
})
}
const {
type,
hostname: savedHostname,
value: savedValue,
errors,
} = await fetch(baseUrl, {
method: 'POST',
headers,
body: JSON.stringify({
type: 'A',
hostname: host,
value: ipValue,
}),
}).then(response => response.json())
if (errors.length) {
throw new Error(JSON.stringify(errors))
}
console.log(`Record ${type} created for ${savedHostname}: ${savedValue}`)
}
updateDns()
node index.js