Serve DNS, so an install is two NS records and nothing else
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 434
- Forks
- 21
- Avg merge
- 18m
- Merged PRs (30d)
- 326
Description
The problem
The honest install today is: buy a domain, set an A record, an MX record, an SPF TXT record, run a script to generate a DKIM key and publish its TXT record, add a DMARC TXT record, add an _xmpps-client._tcp SRV record, install nginx with the stream module compiled in, write a top-level stream {} block, and run certbot. Then set PTR in the VPS panel.
Against a signup form, that loses every time. It is the single largest gap between what this is and what it claims to be, and everything else on the self-hosting list sits below it.
The idea
Serve the zone. The operator delegates a domain or subdomain to the instance with NS records, and Mu answers authoritatively for everything it needs:
| Record | Today | With this |
|---|---|---|
| A / AAAA | set by hand | served |
| MX | set by hand | served |
| SPF TXT | set by hand | served — it knows its own address |
| DKIM TXT | script, then paste | served — it generates the key, so it holds the public half |
| DMARC TXT | set by hand | served |
_xmpps-client._tcp SRV |
set by hand | served |
_acme-challenge TXT |
n/a | served → certificates automatic |
This inverts the dependency. Every item below DNS on the setup list exists because a record has to be published somewhere; if the instance is authoritative, it publishes its own.
Why this is the one that unlocks TLS
ACME DNS-01 requires writing a TXT record under the zone being certified. Doing that from a program normally means either integrating a DNS provider's API per registrar — dozens of providers, credentials in config, the certmagic/lego problem — or falling back to HTTP-01, which needs port 80 free and cannot issue wildcards.
If the instance serves the zone, it answers its own challenge. No credentials, no provider matrix, wildcards available, renewal unattended. Being authoritative is what makes certificate issuance a closed loop, and certificates are what make the reverse proxy unnecessary.
Why it compounds
Adding XMPP cost one manual SRV record per operator, and that is the cheap case. Federation wants _xmpp-server._tcp. SIP would want _sips._tcp. Each new protocol is another paragraph of setup instructions and another way for an install to be silently half-finished.
Serving DNS makes protocol number five zero-configuration instead of a new chore. That is what turns breadth from a cost into a property.
Scope
- Authoritative DNS server.
github.com/miekg/dnsis already in the module graph as an indirect dependency. Answers are computed from the instance's own configuration rather than stored in a zone file, so they cannot drift from what the instance actually does. - ACME with DNS-01 against its own zone.
- In-process TLS on 443, 993, 465 and 5223 — at which point nginx is not part of the install at all.
/admin/statusbecomes self-diagnosing. It already performs external DNS lookups (dnsStatus,internal/app/status.go), which currently sit at "checking…". They become "here is what I serve, and here is what the world sees from outside" — which catches a broken delegation immediately, rather than as mail that silently never arrives.
Each step is useful on its own, and step 1 is what makes 2 and 3 possible.
Delegation: subdomain first, apex as the advanced path
Delegating an apex (example.com) means NS records pointing at a nameserver inside the zone being delegated, so the registrar needs glue records. Supported, fiddly, different at every registrar, and a common way to take a domain offline.
Delegating a subdomain (agent.example.com → box.example.com) needs no glue, because box.example.com is an ordinary A record in the parent zone that the registrar already serves. Two records, both unremarkable, no special registrar feature.
The documented path should be the subdomain — an address like you@agent.example.com — with the apex as an advanced option carrying a warning. This is the difference between a ten-minute install and an afternoon.
Non-negotiable defaults
Authoritative only. Recursion off. Response rate limiting on. A recursive resolver on a public IP is a DNS amplification reflector: an attacker spoofs a victim's source address and the instance sends them many times the traffic they sent it. This is the most common way a self-hosted nameserver becomes somebody else's problem, and it must be a property of the server rather than a setting an operator can get wrong.
What this does not fix, and the docs must say so
- PTR / reverse DNS. Cannot be self-served — it is delegated by whoever owns the IP block, so it stays a field in the VPS control panel. Mail deliverability depends on it matching the HELO name. This is the one item that remains manual.
- IP reputation. A fresh VPS address is frequently already on blocklists, and large providers will junk mail regardless of correct SPF, DKIM and DMARC. This is the actual reason self-hosted mail is hard and no amount of configuration fixes it. Better said plainly in
INSTALL.mdthan discovered a week later. - Availability. DNS on a single box makes the whole domain a single point of failure: if the instance is down, its MX does not resolve, so mail is not merely delayed. Acceptable for self-hosting; should be stated rather than found out.
The install this produces
1. Two NS records: agent.example.com → box.example.com
2. PTR in the VPS panel
3. ./mu --serve
No MX, no SPF, no DKIM script, no DMARC, no SRV, no certbot, no nginx.
Done when
A second operator, starting from a fresh VPS and a domain, reaches a working instance — mail in and out, a chat client connected, a valid certificate — without editing a proxy configuration or publishing a record by hand.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review internal/app/status.go and the ./mu --serve entry point first. Break the proposal into authoritative DNS, ACME DNS-01, in-process TLS, and status diagnostics, using INSTALL.md for the documented subdomain path and remaining PTR/IP-reputation caveats. Done means a fresh VPS can run mail, chat, and valid certificates with only the two NS records, PTR, and ./mu --serve.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- infrastructure, networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100