gitdns.

gitdns.

Your zone file gets a compiler.

gitdns is a git remote for DNS. Push a zone and it is parsed, checked and published. Push a broken one and the commit is rejected with the line, the column, and what to type instead.

~/example.comgit push origin main
git push origin main
remote: gitdns · example.com

remote: error[ZF201]: MX record is missing its preference number
remote:   --> example.com.zone:13:9
remote:    |
remote: 13 | @ IN MX mail.example.com
remote:    |         ^^^^^^^^^^^^^^^^ expected a preference before the mail server name
remote:    |
remote:    = hint: try `@ IN MX 10 mail.example.com.`, where 10 is the preference

remote: error[ZF112]: `CNAM` is not a record type
remote:   --> example.com.zone:17:8
remote:    |
remote: 17 | old IN CNAM www
remote:    |        ^^^^ here
remote:    |
remote:    = hint: did you mean `CNAME`?

remote: 2 errors, 1 warning
remote: nothing was published; the zone still serves its previous commit.
 ! [remote rejected] main -> main (2 errors in example.com.zone)

push.gitdns.

A remote you already know how to use.

Every zone is a git repository. Clone it, edit the file, commit, push. There is no dashboard to click through and no API to script against — the history of your DNS is the history of the repository.

git remote add origin gitdns@gitdns.example:example.com
git push origin main

Push →

Your key, your commit. The pack is read straight into the store — no git binary on the far end.

Check →

Every .zone file in every commit is parsed before a single ref moves.

Publish

What passes is written out with its records parsed and the check that let it through.

check.gitdns.

Anything a nameserver would refuse, refused here first.

Errors stop the push. Warnings do not — they are the things that will serve perfectly well and still ruin your afternoon.

CodeWhat it catchesFor example
ZF1xx Syntax an unclosed (, a TTL of 9x, CNAM where you meant CNAME
ZF2xx Record data 192.168.0.256, an IPv6 address in an A record, hostmaster@example.com in an SOA
ZF3xx Zone rules no SOA, no NS at the apex, a CNAME sharing a name, one RRset with two TTLs
ZF4xx Warnings a missing trailing dot, a TTL of 0, an MX pointing at a name with no records

history.gitdns.

Every version of the zone, kept and readable.

Each push that passes is stored with the zone file exactly as committed, its records parsed out, and the checker's verdict. Read what is live now, or any version before it, without cloning anything.

warning[ZF401] `mail.example.com` has no trailing dot, so it resolves to `mail.example.com.example.com.`
example.com.zone:12:12
12@ IN MX 10 mail.example.com
^^^^^^^^^^^^^^^^ relative name
hint write `mail.example.com.` if you meant the name on its own

Start with one zone.

Create an account, add a zone, push a file. If the file is wrong, you will know before it is anywhere near a resolver.

Push, validation and history work today. Serving the published zones over DNS is next.