DNS Configuration skill for Codex

DNS changes checked at the source, not the cache. Codex queries the authoritative nameservers with dig before and after every change, lowers TTLs ahead of cutovers, tests new hosts with curl --resolve, and diffs entire zones before switching providers. It handles DNSSEC during moves, apex CNAME limits, the SPF ten-lookup cap and a staged DMARC rollout, and it confirms record diffs with you before applying them.

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- dns-configuration

Installs to ~/.agents/skills/dns-configuration/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $dns-configuration, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Plans and verifies DNS changes - A, AAAA, CNAME, ALIAS and apex flattening, MX, TXT, CAA, NS, SRV - plus email authentication records (SPF, DKIM, DMARC, MTA-STS) and zero-downtime migrations between DNS providers or hosts, using dig against authoritative servers instead of trusting caches. Use when pointing a domain at a new host, a record "has not propagated", email lands in spam or fails DMARC, moving a zone from GoDaddy, Route 53 or Cloudflare to another provider, enabling or removing DNSSEC, or auditing a zone for dangling records.

Use it when

  • Pointing a domain or subdomain at a new host
  • Moving a zone between DNS providers or registrars
  • Mail fails SPF, DKIM or DMARC, or lands in spam after adding a sender
  • Auditing a zone for dangling CNAMEs and missing CAA records

Use something else when

How to check the result

Query every authoritative nameserver for the changed names, confirm public resolvers return new values after the old TTL, and check Gmail message headers for spf, dkim and dmarc pass.

The mistake it prevents

Lowering the TTL at the same moment as the change, so resolvers keep the old answer for the full original TTL anyway.

~/.agents/skills/dns-configuration/SKILL.md

--- name: dns-configuration description: Plans and verifies DNS changes - A, AAAA, CNAME, ALIAS and apex flattening, MX, TXT, CAA, NS, SRV - plus email authentication records (SPF, DKIM,… license: MIT ---

Done well means: every change is checked against the authoritative nameservers before and after, TTLs were lowered in advance for planned cutovers, no record is lost in a migration, and email authentication passes for every service that sends as the domain.

DNS edits are outward-facing and can take a site or mail offline for the length of a TTL. Show the exact record diff and get the user’s confirmation before applying it, and keep the previous values in the report so they can be restored.

Inspect first

dig +short NS example.com                       # who is authoritative
dig @ns1.provider.net example.com A +norecurse  # ask the source of truth, not a cache
dig example.com SOA +short                      # serial, negative-cache TTL (last field)
dig +trace www.example.com                      # walk delegation from the root
dig @1.1.1.1 www.example.com +noall +answer     # what a public resolver has cached (TTL counts down)
dig example.com TXT +short ; dig _dmarc.example.com TXT +short
whois example.com | grep -iE 'name server|registrar'   # delegation at the registrar

All of these need network access; in a Codex sandbox with network off, ask for approval or have the user run them. dig is in bind9-dnsutils / bind-utils; on Windows use Resolve-DnsName -Server.

“Propagation” is cache expiry. A resolver that cached the old answer keeps it until the TTL it saw runs out. Failed lookups (NXDOMAIN) are cached too, for the SOA minimum value, so querying a record before creating it can delay it.

Record rules that bite

RuleConsequence
A CNAME cannot coexist with any other record at the same nameNo CNAME at the apex (it has SOA and NS); use the provider’s ALIAS/ANAME/flattening or A/AAAA
MX and NS targets must be hostnames with A/AAAA, never CNAMEs or IPsSome mail servers reject or misroute
Only one SPF TXT record per nameTwo v=spf1 records = SPF permerror, mail fails
TXT values over 255 chars are split into quoted stringsPaste DKIM keys as the provider expects; check with dig TXT that the joined value is intact
Trailing dot means fully qualified in zone fileswww CNAME app.example.com without the dot becomes app.example.com.example.com
PTR (reverse DNS) belongs to whoever owns the IPSet it at the hosting provider, not in your zone
CAA restricts which CAs may issueAdd the CA before switching certificate providers

Changing where a site points

- [ ] 1. Record current values and TTLs from the authoritative servers
- [ ] 2. At least one old-TTL ahead, lower TTL to 300 (wait the OLD TTL before step 4)
- [ ] 3. Bring the new target up; test it with curl --resolve before DNS points at it
- [ ] 4. Confirm the diff with the user, then change the record(s)
- [ ] 5. Verify on authoritative servers, then on 1.1.1.1 and 8.8.8.8
- [ ] 6. Keep the old target serving until old TTL plus a margin has passed
- [ ] 7. Raise TTL back (3600 or more) once stable
curl -sv --resolve www.example.com:443:203.0.113.20 https://www.example.com/ -o /dev/null

--resolve tests the new host with the real hostname, SNI and certificate before any DNS change. Both A and AAAA must point at the new host; a stale AAAA sends IPv6 clients to the old server.

Moving a zone to another DNS provider

  1. Export the full zone from the old provider (zone file or API). Provider UIs often hide records created by integrations; check for _domainkey, _acme-challenge, verification TXT records, SRV records and wildcard entries.
  2. Import into the new provider. Convert provider-specific types (Cloudflare proxied records, Route 53 alias records) to what the new provider supports.
  3. Compare every name and type between old and new authoritative servers before touching the registrar:
OLD=ns1.oldprovider.net; NEW=ns1.newprovider.net
for name in example.com www.example.com api.example.com _dmarc.example.com \
            selector1._domainkey.example.com; do
  for type in A AAAA CNAME MX TXT CAA; do
    a=$(dig +short @"$OLD" "$name" "$type" | sort); b=$(dig +short @"$NEW" "$name" "$type" | sort)
    [ "$a" != "$b" ] && printf 'DIFF %s %s\n  old: %s\n  new: %s\n' "$name" "$type" "$a" "$b"
  done
done; echo "compare done"
  1. Lower the NS TTL at the old provider if it allows. Note the parent (TLD) NS TTL is often 1 to 2 days and cannot be changed.
  2. With confirmation, change nameservers at the registrar. Keep the old zone intact and unchanged for at least 48 hours; resolvers keep using it until the delegation expires.
  3. Make no record edits during the overlap, or make them in both zones.

DNSSEC during a move

If the zone is signed, a naive NS change breaks resolution for validating resolvers (including 1.1.1.1, 8.8.8.8 and many ISP resolvers) because the DS record at the registrar matches the old keys. Safe path: remove the DS record at the registrar, wait for the parent DS TTL to expire, move nameservers, re-enable signing at the new provider, then publish the new DS. A multi-signer key handover avoids the unsigned window but needs both providers to support it.

Email authentication

Every service that sends mail as the domain (Google Workspace, Microsoft 365, the transactional provider, the CRM, the helpdesk) must pass SPF or DKIM with alignment, or DMARC fails. Gmail and Yahoo require SPF, DKIM and DMARC for bulk senders.

example.com.               TXT  "v=spf1 include:_spf.google.com include:amazonses.com -all"
s1._domainkey.example.com. TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."   (or CNAME to provider)
_dmarc.example.com.        TXT  "v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r"
  • SPF allows at most 10 DNS-querying mechanisms (include, a, mx, exists, redirect), counted recursively. Exceeding it is a permerror. Drop unused includes, or send bulk mail from a subdomain with its own SPF.
  • ~all (softfail) while inventorying senders; -all once every sender is listed. DMARC is what actually enforces policy.
  • DMARC rollout: p=none with rua reports for 2 to 4 weeks, fix every legitimate source in the reports, then p=quarantine, then p=reject. Moving straight to reject drops mail from forgotten senders.
  • Domains that never send mail: v=spf1 -all, _dmarc with p=reject, and a null MX (MX 0 .) to stop spoofing.
  • MTA-STS (_mta-sts TXT plus a policy file at https://mta-sts.example.com/.well-known/mta-sts.txt) and TLS-RPT (_smtp._tls TXT) enforce TLS for inbound mail; start in testing mode.

Verify with real headers: send to a Gmail address, open “Show original” and check spf=pass, dkim=pass, dmarc=pass. Sending setup and deliverability practice belong to $transactional-email.

Hygiene and security

  • Dangling records: a CNAME to a deleted cloud resource (S3 bucket, Heroku app, Azure site) lets someone else claim it and serve content on your name. When decommissioning, remove the DNS record first, then the resource.
  • Add CAA for the CAs you use, plus iodef for violation reports.
  • Lock the domain at the registrar (transfer lock, registry lock for critical domains) and enable 2FA on the registrar and DNS accounts.
  • Keep zones in code where the provider supports it (Terraform, OctoDNS, DNSControl) so changes are reviewed.

Verification

  • Authoritative answer matches the intended value on every nameserver: for ns in $(dig +short NS example.com); do dig +short @"$ns" www.example.com A; done.
  • Public resolvers return the new value after the old TTL; if not, check the TTL they report rather than flushing caches you do not control.
  • For mail: headers show SPF, DKIM and DMARC pass; DMARC aggregate reports show no failing legitimate source.
  • After a zone move: the compare loop prints no DIFF lines, and dig +trace ends at the new provider.

Change report template

**Zone:** example.com (authoritative: Cloudflare)
| Name | Type | Before (TTL) | After (TTL) |
|---|---|---|---|
| www | CNAME | old-lb.example.net (3600) | app.fly.dev (300) |
| @ | A | 198.51.100.7 (3600) | 203.0.113.20 (300) |
**Pre-checks:** TTL lowered 2025-06-02 10:00 UTC (old TTL 3600 elapsed); curl --resolve OK
**Post-checks:** all 4 NS return new values; 1.1.1.1 and 8.8.8.8 updated by 11:12 UTC
**Rollback:** restore the "Before" values above; old host stays up until 2025-06-04

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "DNS Configuration"
  short_description: "DNS changes checked at the source, not the cache"
  default_prompt: "$dns-configuration Move example.com from GoDaddy DNS to Cloudflare without breaking email"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem