Secondary DNS / Zone Transfers

Secondary DNS Setup

Nexus GSLB supports RFC 5936 AXFR zone transfers, allowing you to configure secondary (slave) nameservers that pull a copy of the zone. Secondary servers provide:

  • Resilience: the zone continues to resolve if the primary Nexus nodes are unreachable
  • Geographic distribution: secondary PoPs in regions where you have no Nexus nodes
  • CDN secondary integration: Cloudflare, Fastly, and NS1 can pull zone data and serve it from their edge networks
  • Monitoring and auditing: tools like zonemaster can pull and inspect the zone without touching your primary

Prerequisites

  • Nexus GSLB is authoritative for your zone (e.g. gslb.cc)
  • Port 53/TCP is reachable from each secondary server to at least one Nexus node
  • You have API access to create TSIG keys

Step 1 — Enable AXFR on Nexus

Edit /etc/gslb/config.yaml on each Nexus node:

dns:
  domain: "gslb.cc"
  nsNames:
    - "ns1.gslb.cc"     # your Nexus nodes
    - "ns2.gslb.cc"
    - "ns3.example.net" # your secondary, if you want it in NS records
  axfr:
    enabled: true
    requireTsig: true   # recommended

Restart the service on each node:

systemctl restart gslbd

Step 2 — Create a TSIG key

Create one TSIG key per secondary server so that a compromised secondary can be revoked without affecting others.

curl -X POST https://nexus-api.example.com/api/v1/dns/tsig-keys \
  -H "Authorization: Bearer $GSLB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "secondary-bind9.gslb.cc.", "algorithm": "hmac-sha256."}' \
  | jq .

Save the secret — it is shown once.


Step 3 — Configure the secondary

BIND 9

Add to /etc/named.conf or a zone-specific include file:

key "secondary-bind9.gslb.cc." {
    algorithm hmac-sha256;
    secret "dGhpcyBpcyBhIGJhc2U2NC1lbmNvZGVkIHNlY3JldA==";
};

server <nexus-primary-ip> {
    keys { "secondary-bind9.gslb.cc."; };
};

zone "gslb.cc" {
    type slave;
    masters { <nexus-primary-ip>; };
    file "/var/cache/bind/gslb.cc.zone";
    allow-transfer { none; };  # prevent downstream transfers
};

Reload BIND:

rndc reload
# or: systemctl reload named

Trigger an immediate transfer:

rndc retransfer gslb.cc

Verify:

rndc zonestatus gslb.cc
# should show "type: slave", "serial: <unix-ts>", "next refresh: ..."

Knot DNS

In /etc/knot/knot.conf:

key:
  - id: secondary-knot.gslb.cc.
    algorithm: hmac-sha256
    secret: dGhpcyBpcyBhIGJhc2U2NC1lbmNvZGVkIHNlY3JldA==

remote:
  - id: nexus-primary
    address: <nexus-primary-ip>@53
    key: secondary-knot.gslb.cc.

zone:
  - domain: gslb.cc
    master: nexus-primary
    acl: [acl-none]

Reload:

knotc reload
knotc zone-refresh gslb.cc

CoreDNS (Kubernetes / cloud-native)

Install the secondary plugin. In your Corefile:

gslb.cc {
    secondary {
        transfer from <nexus-primary-ip>
        keys hmac-sha256 secondary-coredns.gslb.cc. dGhpcyBpcyBhIGJhc2U2NC1lbmNvZGVkIHNlY3JldA==
    }
    log
    errors
}

Restart CoreDNS. It will pull the zone immediately on startup and refresh based on the SOA Refresh interval (default 3600s in Nexus).


NSD

In /etc/nsd/nsd.conf:

key:
    name: "secondary-nsd.gslb.cc."
    algorithm: hmac-sha256
    secret: "dGhpcyBpcyBhIGJhc2U2NC1lbmNvZGVkIHNlY3JldA=="

zone:
    name: "gslb.cc"
    zonefile: "/var/lib/nsd/gslb.cc.zone"
    request-xfr: AXFR <nexus-primary-ip>@53 secondary-nsd.gslb.cc.
    allow-notify: <nexus-primary-ip> secondary-nsd.gslb.cc.

Reload and transfer:

nsd-control reload
nsd-control force_transfer gslb.cc

Cloudflare Secondary DNS

Cloudflare's Secondary DNS product pulls zone data via AXFR and serves it from Cloudflare's edge.

  1. In the Cloudflare dashboard, go to DNS → Settings → Secondary DNS.
  2. Add a Primary zone with:
    • Zone name: gslb.cc
    • Primary nameserver IP: your Nexus node IP (any one node; Cloudflare will retry others if unreachable)
    • TSIG key name: secondary-cloudflare.gslb.cc.
    • TSIG secret: (the value returned from the API call above)
    • Algorithm: HMAC-SHA256
  3. Cloudflare will perform an immediate zone pull and show a record count.

Note: Cloudflare Secondary DNS pulls the zone and serves it statically. Clients resolving via Cloudflare will receive the full member IP set for each service, not the GSLB-selected single IP. Use short TTLs (30–60s) on your service records to limit the window where stale IPs are served after a member fails.


Verifying the transfer

Test a transfer from the command line:

# Unsigned (requires requireTsig: false)
dig AXFR gslb.cc @<nexus-ip>

# TSIG-authenticated
dig AXFR gslb.cc @<nexus-ip> \
  -y "hmac-sha256:secondary-bind9.gslb.cc.:<base64-secret>"

A successful transfer prints all zone records, beginning and ending with the SOA record.

Check the record count:

dig AXFR gslb.cc @<nexus-ip> | grep -c "^gslb.cc"

Query a specific record on the secondary to confirm it took:

dig A lb.gslb.cc @<secondary-ip>

SOA refresh and TTL behaviour

Nexus synthesises the SOA serial as the current Unix timestamp at the moment of the transfer. Secondaries use the SOA Refresh interval (3600s) and Retry interval (900s) to schedule subsequent pulls. This means:

  • Zone data on secondaries is at most 1 hour stale under normal conditions
  • New pool members or TXT records added to Nexus propagate to secondaries within the Refresh window
  • There is no NOTIFY implementation — secondaries do not receive push notifications when the zone changes. If you need faster propagation, reduce Refresh in the SOA (configurable via dns.adminEmail and dns.nsHostname — serial-only changes require a code change; contact the project if this is a requirement)

Security considerations

  • Each secondary should have its own TSIG key so that a compromised server can be independently revoked via DELETE /api/v1/dns/tsig-keys/<id>.
  • Restrict port 53/TCP to known secondary IPs at the firewall in addition to TSIG — defence in depth.
  • AXFR exposes the full zone, including _acme-challenge TXT records (if any are currently live during a cert renewal). These are transient and harmless, but operators should be aware.
  • Do not advertise secondary nameservers in your NS records until you have verified the transfer is working.


Was this article helpful?
© 2026