How to get a REST API to manage your DNS ? /
Get a DNS zone manager

30/03/2024

From seamless automation with REST APIs to robust tools for DNS record control, custom DNS services make simpler how websites are managed and maintained.

Default DNS Management Simplified

When you buy a domain from places like Google Domains, handling your DNS records is done right there. It’s easy for many folks, but it has its limits. For example, there’s no fancy tool like a REST API for managing your domains. This means you can’t automate tasks such as creating subdomains using scripts or smoothly deploying projects from your command line.

Imagine a scenario where you want a new subdomain every time you start a new project. Sadly, with the basic DNS management provided by default, that’s not possible.

Custom DNS Management: A Better Option

The world of DNS management isn’t just limited to what domain registrars offer. There are third-party services like Cloudflare DNS, Amazon Route 53, or DNSimple. These services bring in a lot more flexibility and tools for managing your DNS records.

One great thing about these custom DNS services is that they come with REST APIs. This means developers can talk to their DNS settings using code, opening up a whole new world of automation. Imagine making a simple request to create a new subdomain or updating your DNS records automatically when your infrastructure changes. That’s the power custom DNS management offers.

Moving to Custom DNS Servers

If you want to switch to a custom DNS service, you’ll need to redirect your domain’s DNS queries from your registrar’s default servers to the servers of your chosen DNS provider.

In my situation, I decided to have Hetzner handle my DNS, but my domain is currently looked after by Google.

To make this change, I had to update the name servers, following the instructions provided in the screenshots.

Hetzner new server name :

Google domain registrar :

How to create a record with the Hetzner API

Here’s a small script to get the zones and to create a new record.

The api key is store in a .env. file at the root of my project.

You need to install dotenv and axios

npm install dotenv 
npm install axios 
touch .env

The .env file looks like this :

hetznerDNSToken = sbfwolkdnazhdhl9833

The script :

const dotenv = require('dotenv');
dotenv.config();

const axios = require('axios');



const axiosConfig = {
    headers: {
        'Auth-API-Token': process.env.hetznerDNSToken
      }
}

/**
 * Retrieves all DNS zones from Hetzner DNS API.
 * @async
 * @returns {Promise<Array>} An array containing information about all DNS zones.
 * @throws {Error} If an error occurs during the fetch process or if no zones are found.
 */
const getZones = async () => {

    const response = await axios.get('https://dns.hetzner.com/api/v1/zones', axiosConfig);

    if(!response.data) throw new Error('Error fetching zones:', response.data);

    const {zones} = response.data;

    if(!zones) throw new Error('No zones found');

    return zones;
};

/**
 * Retrieves all records associated with a specific DNS zone from Hetzner DNS API.
 * @async
 * @param {string} zoneId - The ID of the DNS zone to retrieve records from.
 * @returns {Promise<Object>} An object containing information about DNS records.
 * @throws {Error} If an error occurs during the fetch process.
 */
const getRecords = async (zoneId) => {

    const response = await axios.get(`https://dns.hetzner.com/api/v1/records?zone_id=${zoneId}`, axiosConfig);

    if(!response.data) throw new Error('Error fetching records:', response.data);

    return response.data;
};

/**
 * Creates a DNS record within a specific DNS zone using the provided data.
 * @async
 * @param {object} requestData - An object containing data required to create a DNS record.
 * @param {string} requestData.value - The value of the DNS record.
 * @param {number} requestData.ttl - The Time-To-Live (TTL) of the DNS record.
 * @param {string} requestData.type - The type of the DNS record (e.g., 'A', 'CNAME', 'MX').
 * @param {string} requestData.name - The name of the DNS record.
 * @param {string} requestData.zone_id - The ID of the DNS zone where the record will be created.
 * @returns {Promise<Object>} An object containing information about the created DNS record.
 * @throws {Error} If any required property is missing or if an error occurs during the creation process.
 */
const createRecord = async (requestData) => {

    const requiredProperties = ['value', 'ttl', 'type', 'name', 'zone_id'];

    for (const prop of requiredProperties) {
        if (!(prop in requestData)) {
          throw new Error(`Missing required property: ${prop}`);
        }
      }

    const response = await axios.post('https://dns.hetzner.com/api/v1/records', requestData, axiosConfig);

    return response.data;
};




  (async () => {


    const zones = await getZones();

    console.log(zones);


    const records = await getRecords(zones[0].id);

    console.log(records);


    const response = await createRecord({
        zone_id: zones[0].id,
        ttl: 86400,
        name: 'testa',
        type: 'A',
        value: '51.68.227.24'
    });

    console.log(response);

  })().catch(console.log);



Test your custom DNS server with dig

dig @1.0.0.1 lancieux.antoinebrossault.com. AAAA

This command is like asking a specific phone book (the DNS server at 1.0.0.1) for the phone number (IPv6 address) associated with a particular name (lancieux.antoinebrossault.com).

The part AAAA specifies that we’re specifically looking for an IPv6 address.

So, the command is basically saying: « Hey, DNS server at 1.0.0.1, tell me the IPv6 address for the name lancieux.antoinebrossault.com. »

Result


; <<>> DiG 9.10.6 <<>> @1.0.0.1 lancieux.antoinebrossault.com. AAAA ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54149 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;lancieux.antoinebrossault.com. IN AAAA ;; AUTHORITY SECTION: antoinebrossault.com. 3600 IN SOA hydrogen.ns.hetzner.com. dns.hetzner.com. 2024033004 86400 10800 3600000 3600 ;; Query time: 113 msec ;; SERVER: 1.0.0.1#53(1.0.0.1) ;; WHEN: Sat Mar 30 22:28:50 CET 2024 ;; MSG SIZE rcvd: 118

Under the Authority section we can see our new servers


;; AUTHORITY SECTION: antoinebrossault.com. 3600 IN SOA hydrogen.ns.hetzner.com. dns.hetzner.com. 2024033004 86400 10800 3600000 3600