micro / micro/mu

Serve DNS, so an install is two NS records and nothing else

Open
#1,470 0 comments 0 reactions 0 assignees View on GitHub

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

  1. Authoritative DNS server. github.com/miekg/dns is 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.
  2. ACME with DNS-01 against its own zone.
  3. In-process TLS on 443, 993, 465 and 5223 — at which point nginx is not part of the install at all.
  4. /admin/status becomes 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.combox.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.md than 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.