Automating DNS updates with GoDaddy API and Bash scripts

DNS records are small, yet a mistyped address can send customers to the wrong server, break a VPN, or expose a retired service. The change itself takes seconds in the GoDaddy console; finding who changed it, why it happened, and how to reverse it can take much longer.

A GoDaddy API call wrapped in Bash turns that console action into a controlled workflow with validation, audit output, and repeatable deployment. The aim is clever scripting; it is a small, verifiable change that an Australian administrator can run from a server, laptop, or CI runner without relying on browser state.

Why DNS automation earns its keep

Manual updates through a web console leave weak audit trails. Two administrators can inspect the same record and see different values, while an emergency change made from a phone disappears into browser history. Automation creates a consistent sequence: validate, update, verify, and record.

A Bash script can also compare the current domain records with the desired state before making a change. That supports repeatable deployment, prevents accidental overwrites, and gives infrastructure teams a standard way to manage hostnames across different DNS providers.

Infrastructure planning discussions often compare cloud versus in-house tooling. A small API integration is usually a better fit than a full service-management platform, provided the script remains readable and its failure modes are understood.

Prepare the GoDaddy API safely

Treat the GoDaddy API credentials like production keys. The account commonly exposes a shopper ID, API key, and secret, which should come from a dedicated automation identity or team account rather than a personal login. Store them in a secret manager and rotate them on a schedule. The sample authentication below should also be checked against the current developer documentation for the account.

Before updating a record, establish its exact identity. GoDaddy records may be represented by a hostname such as www, while an apex record may use @. Record types also carry different fields: a simple address record needs only a value and TTL, whereas MX and service records need priority, port, protocol, and weight. The first version of the workflow should handle only simple record types.

Australian domain ownership adds another boundary. Existing .com.au and .au domains are generally eligible for DNS changes, but ACMA and auDA require Australian presence when those domains are registered or transferred. A DNS script cannot resolve an ownership eligibility problem. Many Australian organisations also purchase domains through local resellers, while GoDaddy API billing may use another currency, so invoices may need reconciliation against AUD and card-issuer fees.

Build a conservative Bash update workflow

Start with one single-valued A, AAAA, or CNAME record on a dedicated test hostname. The script should fetch the current records, detect an already-correct value, preserve unrelated records, and submit only the intended change. It should also fail clearly when a dependency, credential, or API response is wrong.

This example uses the GoDaddy records endpoint and the common shopper authentication headers. Check the current API schema before production use, particularly the PATCH payload format.

#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

: "${GODADDY_SHOPPER_ID:?missing shopper ID}"
: "${GODADDY_API_KEY:?missing API key}"
: "${GODADDY_API_SECRET:?missing API secret}"
: "${DNS_DOMAIN:?missing domain}"
: "${DNS_NAME:?missing record name}"
: "${DNS_TYPE:?missing record type}"
: "${DNS_VALUE:?missing record value}"
DNS_TTL="${DNS_TTL:-600}"

case "$DNS_TYPE" in
  A|AAAA|CNAME) ;;
  *) printf 'Unsupported record type: %s\n' "$DNS_TYPE" >&2; exit 2 ;;
esac

work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT

cat > "$work/curl.conf" <<EOF
header = "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}"
header = "X-Shopper-Id: ${GODADDY_SHOPPER_ID}"
EOF

curl --fail --silent --show-error --config "$work/curl.conf" \
  --connect-timeout 10 --max-time 30 \
  "https://api.godaddy.com/v1/domains/${DNS_DOMAIN}/records" \
  --output "$work/current.json"

if jq -e --arg n "$DNS_NAME" --arg t "$DNS_TYPE" \
  --arg d "$DNS_VALUE" --argjson ttl "$DNS_TTL" \
  '.items | any(.name == $n and .type == $t and .data == $d and .ttl == $ttl)' \
  "$work/current.json" >/dev/null; then
  printf '%s already has the requested value\n' "$DNS_NAME"
  exit 0
fi

jq --arg n "$DNS_NAME" --arg t "$DNS_TYPE" \
  --arg d "$DNS_VALUE" --argjson ttl "$DNS_TTL" \
  '(.items | map(select(.type != $t or .name != $n)))
   + [{name:$n, type:$t, ttl:$ttl, data:$d}]' \
  "$work/current.json" > "$work/desired.json"

curl --fail --silent --show-error --config "$work/curl.conf" \
  --connect-timeout 10 --max-time 30 \
  --request PATCH --header "Content-Type: application/json" \
  --data-binary "@$work/desired.json" \
  "https://api.godaddy.com/v1/domains/${DNS_DOMAIN}/records"

printf 'Updated %s in %s\n' "$DNS_NAME" "$DNS_DOMAIN"

The jq merge retains records that were not targeted, while the early exit makes a repeated run harmless. Multiple values under the same name and type need explicit handling rather than this simplified replacement. Archive the before-and-after JSON as a CI artifact so the change can be reviewed and reversed.

Deploy from one controlled runner

Run the script from a designated administrator account, CI job, or systemd timer rather than allowing every engineer to update DNS independently. A runner hosted in an Australian cloud region such as Sydney’s ap-southeast-2 or Melbourne’s ap-southeast-4 keeps access and logs close to the team, although a small on-premises server can work equally well.

Keep time handling explicit. New South Wales and Victoria move between AEST and AEDT, while Queensland does not observe daylight saving. Store timestamps in UTC, include the IANA time zone in audit records, and avoid scheduling decisions that depend on a laptop’s local clock.

Retries need limits. A 429 response or temporary 5xx error can be retried with exponential backoff, but the script should honour any Retry-Header guidance and stop after a defined attempt count. For teams already using SharePoint, the runbook and SharePoint change records can provide a durable audit trail beside the CI log and approval history.

Verify and observe every change

After the API accepts an update, fetch the record again and compare its value and TTL with the intended state. Then query the authoritative name servers and at least one recursive resolver with tools such as dig. An API success only confirms that GoDaddy accepted the request; it does not prove that every resolver has received the new answer.

Include an Australian ISP resolver in the checks because its cache may differ from public resolvers such as Cloudflare or Google. Account for the previous TTL, since cached answers can remain valid after the authoritative record changes. A staged test hostname often gives a clearer propagation signal than an urgent production address.

Monitoring should report successful updates, unexpected differences, failed API calls, and post-change resolution results. The site's performance analysis in F# provides a useful model for turning operational measurements into actionable alerts rather than leaving dashboards for occasional inspection.

Keep rollback separate from the normal update path. A saved previous value allows an authorised operator to restore the record, but automatic rollback can also undo a valid change if it triggers during a legitimate address migration. Require explicit confirmation and record the reason for every reversal.

Practical controls for a reliable DNS workflow

A small workflow still needs operational boundaries:

  • Allow only approved domains and record names.
  • Fetch and compare records before changing one.
  • Require review for MX, NS, and apex changes.
  • Keep API secrets in a managed vault.

Each release should pass a short, repeatable verification sequence:

  • Test with a dedicated, low-risk hostname.
  • Confirm values through GoDaddy and public resolvers.
  • Check that unrelated records remain unchanged.
  • Save the previous value, timestamp, and operator.
  • Alert on every failed or unexpected change.

Choose one low-risk A record on a domain you manage, run the workflow from a test administrator, and confirm the result through GoDaddy and two Australian resolvers. Once that path is proven, schedule the approved process and retain its rollback data with the corresponding change record.

Experience

Information Technology Consulting

Independent Practice

Provides IT consulting services focused on infrastructure planning, cloud migration strategy, and systems architecture. Engagements draw on years of hands-on sysadmin and development experience across Linux, Windows, and hybrid environments.

K9 Search & Rescue Volunteer

Ongoing

Active participant in K9 Search & Rescue operations, combining technical logistics skills with field support for canine search teams.

Karl Katzke's Blog

October 2006 – May 2014

Published a long-running personal technology blog covering cloud vs. in-house infrastructure, F# and Mono on OSX, hardware vendor critiques, RAID card performance analysis, and sysadmin storytelling. Notable posts include "When Sysadmins Ruled the Earth" (May 15, 2014) and "Getting Started with F# and Mono on OSX" (December 22, 2012).

Credentials

A small badge icon with a shield shape in muted blue tones on a light background

Systems Administration

Deep experience with Linux (RHEL, SLES, CentOS), high-availability clusters, and STONITH configurations.

A small badge icon with a gear shape in muted blue tones on a light background

Cloud Infrastructure

Practical knowledge of AWS EC2, reserved instances, and cost analysis for cloud vs. on-premises deployments.

A small badge icon with a code symbol in muted blue tones on a light background

Development

Proficient in F#, PHP (Symfony), and cross-platform tooling including Mono and MonoDevelop on OSX.

Studies

F# & Functional Programming

Self-directed, 2012

Explored strongly typed functional programming with F# on OSX using the Mono runtime. Published a detailed getting-started guide covering toolchain setup and cross-platform game development research.

High-Availability & Cluster Management

Professional Development, 2009

Configured and documented crm_mon email alerting for STONITH events on SLES11-HAE clusters, integrating with Nagios monitoring for production environments.

Hardware & Storage Performance

Ongoing

Conducted hands-on benchmarking of SATA/SAS RAID controllers including HighPoint RocketRaid 2740 and LSI/SuperMicro AOC-USASLP2-H8iR, comparing against software RAID configurations.

Skills

A small icon representing a server with clean geometric lines in slate blue

Linux Administration

RHEL, SLES, CentOS — package management, kernel tuning, HA clustering, and monitoring integration.

A small icon representing a cloud shape with clean geometric lines in slate blue

Cloud Architecture

AWS EC2, reserved-instance planning, cost modeling, and hybrid infrastructure strategy.

A small icon representing code brackets with clean geometric lines in slate blue

F# & .NET/Mono

Functional programming on OSX, MonoDevelop toolchain, and cross-platform game-dev exploration.

A small icon representing a database cylinder with clean geometric lines in slate blue

PHP & Symfony

Web application development with the Symfony framework and the broader PHP ecosystem.

A small icon representing a storage drive with clean geometric lines in slate blue

Storage & RAID

SATA/SAS controller evaluation, md RAID configuration, and performance benchmarking.

A small icon representing a shield with clean geometric lines in slate blue

High Availability

Pacemaker, STONITH, crm_mon alerting, and Nagios integration for production cluster monitoring.