DNS Zone Blocks
Six blocks that run authoritative DNS from a storage: records live as documents, a zone file is rendered from them whole, and nothing reaches a nameserver until every server has checked the exact bytes about to be sent.
A zone file is an output, never a document you maintain. Records are ordinary documents in a storage, and the file your nameservers serve is rendered from them in one piece, every time. There is no partial edit and no diff to repair: render, check, push, verify.
| Block | What it does | Touches a nameserver |
|---|---|---|
dnszone_import | Turns a Route53 export into records, timers and delegation, ready to store. | No |
dnszone_render | Turns stored records into a complete zone file, with a report of every decision it made. | No |
dnszone_slot_status | Reports which per-domain records a member of a zone group has answered for, and which nobody has. | No |
dnszone_check | Validates the file on every nameserver. Writes nothing, anywhere. | Reads only |
dnszone_push | Replaces the live file and reloads, per server. Only reachable once the check passed everywhere. | Yes, writes |
dnszone_verify | Asks every server which version it is actually serving, and whether they agree. | Reads only |
One record shape, everywhere
What the import block produces is what a storage holds and what the render blocks read. A record carries its owner, type, time to live and values, plus a few fields describing its own disposition inside a group.
- Owners are stored relative to the domain:
@,www,*,mail._domainkey. That makes one record set serve several domains:wwwrenders correctly under every one of them without a value being rewritten. - The start-of-authority record and the domain's own nameserver set are not records. They come back on their own outputs and every rendered zone carries its own, so nothing in the editable set invites a hand-edited serial number.
Import reads a Route53 export and nothing else
dnszone_import accepts the AWS document, a bare array, or either as pasted JSON text, so reading a file and pasting into a box are not two different flows. Escaped characters are expanded on the way in, so a wildcard arrives as a character your rules can match.
Two things it refuses to guess:
- Routing policies. Weighted, latency, geolocation and failover answers have no zone file equivalent. Importing one would collapse several answers into one arbitrary answer, so the block refuses and names the records it refused.
- The serial number. It is discarded on import, because the serial is stamped at push time. A stored copy would disagree the first time anybody edited it.
Record order is preserved exactly as the export gave it, which is what makes the same stored state render to the same bytes every time.
Zone groups: one record set, several domains
A zone group is one set of records with several domains rendered from it. You edit one domain and the others are rendered from the same records, so there is no state that can drift and no synchronisation that can fail halfway.
Setting the base domain on dnszone_render selects that shape. Every value of every base record then takes one of four dispositions, from the first matching rule you gave it.
| Disposition | What happens |
|---|---|
| Verbatim | The default. The same value appears under the new domain. |
| Rewrite | A value that names the base domain is re-aimed at this member's. Opt-in, reported, and refused outright when it would change nothing. |
| Per-domain | The base value is not copied at all. The record becomes a named slot this domain fills from its own records. |
| Note | Copied verbatim and flagged for a human to look at. |
A rewrite that changes nothing is a hard failure. Providers are inconsistent about whether a stored target ends in a dot, so a rule written against the wrong form would leave the member domain pointing at the base domain. The renderer refuses rather than accepting a rewrite with no effect.
Some records have to be per-domain slots. Each of these has to be answered by the domain itself or explicitly marked as never applicable:
- Certificate validation records are issued per domain. Copying the base domain's publishes a validation record for a certificate nobody requested there.
- Mail signing keys are minted per sending domain. A copied key signs nothing and collides with the real one the day that domain starts sending.
- Ownership verification tokens prove nothing under another domain.
Filled, not applicable and empty are three states
dnszone_slot_status reports the same picture without rendering anything, for an overview screen that has to show the gaps before anyone renders.
| State | Meaning |
|---|---|
| Filled | This domain carries its own record for the slot. |
| Not applicable | Somebody recorded why this domain will never have one. |
| Empty | Nobody has looked at it yet. |
The last two are different on purpose. A domain that sends no mail will never have a mail signing key, and writing that down with its reason is finished work. An empty slot is unfinished work: the render reports itself incomplete, and in strict mode it refuses to render at all.
Rendering produces the whole file
Without a base domain, the same render block produces a plain zone file: the same records, timers and time-to-live values the zone holds today, so your servers are a drop-in addition while the old delegation is still live. Two things are the platform's own.
- The serial is a placeholder that the push stamps with the time it was pushed. That is monotonic without anybody having to remember yesterday's number.
- The nameserver set is the zone's existing servers plus yours. Both sets are authoritative and serve identical data. Nothing here touches your registrar delegation, which stays a decision you make separately.
Alias records are the exception. A zone file can only hold the addresses an alias resolves to at this moment, and those go stale silently when the target moves. So flattening is opt-in, and every flattened record comes back on its own output with the value it resolved to, on every render. A target that does not resolve is left out of the file, with a comment saying so.
Nothing reaches a server without passing the gate
The render blocks cannot push, and dnszone_push will not run ungated. It requires the results from dnszone_check and refuses unless every server in its own list has a passing check whose fingerprint matches a fresh hash of the exact bytes about to be sent.
- A validation failure on any single server leaves every server's live file untouched, including the ones that would have accepted it.
- A flow cannot check one file and push a different one, because the bytes are hashed again at the moment of pushing.
- An incomplete render is refused too. A zone with a per-domain slot nobody answered for parses perfectly and is missing a record, which no validator can see.
Past the gate it is not atomic. The servers are independent, each validates and swaps on its own, and one that rejects the file keeps serving what it had. Follow every push with dnszone_verify: disagreement between servers is the only failure that is invisible from the stored copy.
The normal flow, end to end
Import once, into a storage
From then on the storage is the source of truth and the export is history.
Render the file for the domain
Read the report: it names every rewrite, every flattened alias with the value it resolved to, and every gap.
Fill the gaps
If any slot is empty, fill it or record why it will never apply. Do not push past it.
Check
Check the rendered bytes on every server.
Push
It only proceeds if every check passed on those exact bytes.
Verify
Servers that disagree are the failure you cannot see from the stored copy.
Next steps
All DNS Blocks Full pin reference for each of the six blocks. Storages The document model the records live in. Service Providers Where credentials live when a flow has to reach something outside the cluster.Frequently asked
How does RUAL manage DNS zones?
Records live as documents in a storage and the zone file is rendered from them whole, every time. There is no partial edit and no diff to repair. The normal cycle is import once, render, check the exact bytes on every nameserver, push only what passed, then verify that the servers agree.
Can a RUAL DNS push go out without being checked?
No. The push block requires the check results and refuses unless every nameserver in its list has a passing check whose fingerprint matches a fresh hash of the bytes about to be sent. A failure anywhere leaves every server's live file untouched, and a flow cannot check one file and push a different one.
Is it safe to simulate a DNS push in RUAL?
No. Simulation holds back storage writes but does not hold back outbound integrations, so a simulated push really connects to your nameservers and really replaces their zone files. Simulate the render and the check freely, and run the push deliberately.