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.
Karl Katzke