Adding a DNS A record for the apex / root zone

Hey all,

I am using the Hashicorp DNS provider against BIND9, and having generally pretty good luck with it. However, I need to define A records for the apex of a zone (for Active Directory domain controllers) - something you’d use the “@” character to reference in BIND config.

I’m trying to use the dns_a_record_set ( Terraform Registry ) resource for this purpose and can add other records just fine.

I cannot figure out how to actually create an apex record. Setting the name field to “”, “@”, “.”, “_” do not work. Omitting the name field does not work. Setting the zone field to “.” and putting the name as the zone name does not work.

How do I create this record? Do I have to bounce out to nsupdate like a sucker?

I implemented this using an out of band process, here’s what I ended up with:

# The Terraform DNS provider doesn't support Apex A records (yet).
# This implements the same functionality using an external program.
resource "null_resource" "apex_a_record" {
  triggers = {
    domain = module.config.ad.domain
    dns_master_ip = data.onepassword_item.tsig_key.url
    tsig_key = data.onepassword_item.tsig_key.password
    dns_apex_ips = join(",", local.dc_ips)
  }

  # Create time provisioner
  provisioner "local-exec" {
    command = "${path.module}/scripts/nsupdate.sh add ${self.triggers.domain} ${self.triggers.dns_master_ip} ${self.triggers.tsig_key} ${self.triggers.dns_apex_ips}"
  }

  # Destroy-time provisioner
  provisioner "local-exec" {
    when    = destroy
    command = "${path.module}/scripts/nsupdate.sh remove ${self.triggers.domain} ${self.triggers.dns_master_ip} ${self.triggers.tsig_key} ${self.triggers.dns_apex_ips}"
  }
}

and then in the script:

#!/bin/bash

ACTION=$1
DOMAIN=$2
MASTER_DNS_SERVER=$3
TSIG_KEY=$4
IPS=$5

# Convert comma-separated IPs to newline-separated for nsupdate
IPS_NEWLINE=$(echo "$IPS" | tr ',' '\n')

# Create nsupdate commands
NSUPDATE_CMDS=$(mktemp)
if [ "$ACTION" == "add" ]; then
  echo "server $MASTER_DNS_SERVER" > $NSUPDATE_CMDS
  echo "zone $DOMAIN" >> $NSUPDATE_CMDS
  echo "update delete $DOMAIN A" >> $NSUPDATE_CMDS
  for IP in $IPS_NEWLINE; do
    echo "update add $DOMAIN 300 A $IP" >> $NSUPDATE_CMDS
  done
  echo "send" >> $NSUPDATE_CMDS
elif [ "$ACTION" == "remove" ]; then
  echo "server $MASTER_DNS_SERVER" > $NSUPDATE_CMDS
  echo "zone $DOMAIN" >> $NSUPDATE_CMDS
  echo "update delete $DOMAIN A" >> $NSUPDATE_CMDS
  echo "send" >> $NSUPDATE_CMDS
else
  echo "Invalid action. Use 'add' or 'remove'."
  exit 1
fi

# Execute nsupdate with TSIG key
nsupdate -y hmac-sha256:tsig-key.:$TSIG_KEY $NSUPDATE_CMDS
EXIT_CODE=$?

rm $NSUPDATE_CMDS

if [ $EXIT_CODE -ne 0 ]; then
    exit $EXIT_CODE
fi

Hopefully this saves someone else some time.