DNS records
Every DNS record a domain hosted on Nixt Server needs, what each one does, how to print them again, and how to enter them at a DNS provider.
Nixt Server tells you exactly what to publish. init prints every record for the first domain, and versealx-server dns prints them again for any domain at any time. After you publish them, versealx-server doctor checks what is actually in DNS against what the server needs.
The examples on this page use example.com as the mail domain, mail.example.com as the server’s host name, and 192.0.2.10 and 2001:db8::10 as its public addresses.
Printing the records
sudo -u versealx versealx-server dns example.com --config /etc/versealx-server/versealx-server.toml
Leave out the domain to print the records for every domain the server hosts, each group headed by ; <domain>. The records come from the same place init takes them, so the two commands always agree. A domain the server does not host is refused with example.com is not a domain of this server.
dns reads the store directly, so it works whether or not the server is running.
Trying records before you publish them
Before you change your registrar’s zone, you can check the records you plan to publish. Type them in, and every check the server makes of the domain says what it would say with them. Your records replace what DNS has now for their names and types, and everything else is read from DNS as usual. Nothing is published.
On the console, use the Try records before publishing card on the domain’s page. Write one record a line: its type, its name and its value, such as TXT _dmarc.example.com v=DMARC1; p=reject. The types you can try are TXT, MX (the value is the preference and the host), A and AAAA. From the command line:
sudo -u versealx versealx-server admin try dns example.com \
--record 'TXT _dmarc.example.com v=DMARC1; p=reject; rua=mailto:dmarc@example.com' \
--record 'MX example.com 10 mx.example.com'
Through the API, send POST /tenants/{tenant}/try/dns with domain and records, each a name, a type and a value. You can try up to 50 records at once, all at or under the domain.
The records
This is what dns prints for a node that delivers mail directly. Lines that begin with ; are notes, not records.
mail.example.com. IN A <this host's public address> ; AAAA too, if it has one
example.com. IN MX 10 mail.example.com.
example.com. IN TXT "v=spf1 mx -all"
; only this host sends. Add `include:<relay>` before `-all` if you ever
; send through one, or everything you send will fail SPF, and then
; DMARC alignment, and the large receivers will refuse it
; (RFC 7208 §2.6.4)
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com" ; start at p=none, read the reports, then tighten
_versealx-verify.example.com. IN TXT "versealx-verify=<token>"
; the RSA key below is two quoted strings, which is how a zone file
; holds a value longer than 255 characters. A web form with a single
; value field wants the text between the quotes instead, joined, with
; the quotes and the space between them taken out
<selector>r._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=<first part>" "<rest of the key>"
<selector>e._domainkey.example.com. IN TXT "v=DKIM1; k=ed25519; p=<key>"
_mta-sts.example.com. IN TXT "v=STSv1; id=20260914120000"
mta-sts.example.com. IN CNAME mail.example.com.
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@example.com"
_submissions._tcp.example.com. IN SRV 0 1 465 mail.example.com.
_submission._tcp.example.com. IN SRV 1 1 587 mail.example.com.
_imaps._tcp.example.com. IN SRV 0 1 993 mail.example.com.
_imap._tcp.example.com. IN SRV 1 1 143 mail.example.com.
_pop3s._tcp.example.com. IN SRV 0 1 995 mail.example.com.
_pop3._tcp.example.com. IN SRV 1 1 110 mail.example.com.
_jmap._tcp.example.com. IN SRV 0 1 443 mail.example.com.
; and a PTR for this host's address pointing back at mail.example.com
After the domains, dns prints the host’s DANE record (see DANE (TLSA)) and ends with:
; Check what is published with: versealx-server doctor
; The `_mta-sts` id only has to change when the policy does (RFC 8461 §3.1),
; so if one is already published and the policy has not changed, leave it.
For a domain that is not marked verified yet, dns adds a note with the command that marks it.
Summary
| Record | Name | Required for | Checked by doctor |
|---|---|---|---|
| A and AAAA | mail.example.com | Everything. The MX names this host, and a host that resolves nowhere is an MX that does not exist. | Yes, with reverse DNS |
| MX | example.com | Receiving mail. | Yes |
| SPF (TXT) | example.com | Mail you send passing SPF. | Yes |
| DMARC (TXT) | _dmarc.example.com | Telling receivers what to do with mail that fails, and receiving reports. | Yes |
| Ownership token (TXT) | _versealx-verify.example.com | Proving the domain is yours. | Yes |
| DKIM (TXT), two | <selector>r._domainkey.example.com, <selector>e._domainkey.example.com | Mail you send passing DKIM. | Yes, key by key |
| MTA-STS (TXT) | _mta-sts.example.com | Telling senders to fetch your MTA-STS policy. | Yes |
| MTA-STS host (CNAME) | mta-sts.example.com | Letting senders fetch the policy. | Through the TXT check |
| TLS reporting (TXT) | _smtp._tls.example.com | Receiving reports about failed TLS deliveries. | Yes |
| SRV, seven | _submissions._tcp, _submission._tcp, _imaps._tcp, _imap._tcp, _pop3s._tcp, _pop3._tcp, _jmap._tcp | Mail apps configuring themselves. | No |
| PTR | The reverse name of 192.0.2.10 | Other servers accepting your mail. | Yes |
| TLSA | _25._tcp.mail.example.com | DANE, optional. | Yes |
| Key directory (CNAME) | openpgpkey.example.com | Mail apps finding people’s encryption keys, optional. | No |
Each record in detail
Address records
mail.example.com. IN A 192.0.2.10
mail.example.com. IN AAAA 2001:db8::10
The host name must resolve to the address other servers and mail apps reach. doctor warns if the name resolves only to an address the internet does not route to — a 10.x, 172.16–31.x, 192.168.x or 100.64–127.x address, for example. That is expected if your own resolver answers with a private address (split-horizon DNS), but the public DNS must give the public address.
MX
example.com. IN MX 10 mail.example.com.
Other servers deliver mail for example.com to the host the MX names. If the MX still names your previous provider, mail keeps going there. doctor reports BAD when the MX names some other host.
If you add a second MX host, also list it in [mta_sts] mx, or senders that hold your MTA-STS policy will not deliver to it.
SPF
example.com. IN TXT "v=spf1 mx -all"
v=spf1 mx -all says that only the hosts your MX record names may send mail as example.com. That is right for a server that delivers mail itself.
When the server sends through a relay, the mail leaves from the relay’s addresses, so the record must name the relay too. init --relay smtp.relay.example.net prints:
example.com. IN TXT "v=spf1 mx include:relay.example.net -all"
; `include:` above is the relay's own list of sending addresses. Check
; the name against what your provider documents — some publish it at
; a different one — and start at `~all` if you would rather watch the
; reports before rejecting
The include: uses the relay host’s parent domain. Check your provider’s documentation for the name it publishes its sending addresses under.
doctor compares the record with how the node actually sends. It reports BAD when a relay is configured and the record does not include it, and warn when the record includes a relay but none is configured.
DMARC
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
p=none asks receivers to report but not to act. Read the reports for a few weeks, then move to p=quarantine and p=reject. Every domain the server hosts accepts mail at dmarc@ and tlsrpt@ even without an account of that name, and files the reports it receives there. See Email authentication.
Ownership token
_versealx-verify.example.com. IN TXT "versealx-verify=<token>"
The token is made when the domain is added. It is not secret. versealx-server admin get tenants/1/domains/example.com shows it under verification. See Domain verification for what it controls and for the other two records that also prove ownership.
DKIM
<selector>r._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=<first part>" "<rest of the key>"
<selector>e._domainkey.example.com. IN TXT "v=DKIM1; k=ed25519; p=<key>"
Every domain has two signing keys: an RSA key (selector ending in r) and an Ed25519 key (selector ending in e). The server signs every message with both, so publish both. When keys are made without a selector name, the selector is built from the date they were made.
A 2048-bit RSA public key is longer than the 255 characters one DNS text string can hold, so the RSA record is printed as two quoted strings, which is how a zone file holds it. What to enter depends on your provider:
- A zone-file import, or a form that takes several strings: enter it as printed.
- A web form with a single value field: enter only the text between the quotation marks, joined into one piece, with the quotes and the space between them removed. The provider splits it for you. Pasting the quoted form into a single field publishes the quotation marks, and the key then verifies nowhere.
doctor looks up every selector the node signs with and compares the p= value with the key in the store:
doctor finding | Cause |
|---|---|
… is the key this node signs with | Correct. |
… is not published | Publish the record. |
… publishes the first N characters of a M-character key | The provider kept only the first string. Paste the whole value. |
… publishes a different key | An old selector’s record, or another server’s key. |
… publishes p= with nothing after it, which revokes the key | An empty p= withdraws the key; receivers refuse mail signed with it. |
… exists but has no p= tag | Something other than a DKIM key is at that name. |
this domain has no signing keys | Generate a pair; see Email authentication. |
MTA-STS
_mta-sts.example.com. IN TXT "v=STSv1; id=20260914120000"
mta-sts.example.com. IN CNAME mail.example.com.
The TXT record tells sending servers that example.com has an MTA-STS policy; the CNAME lets them fetch it from https://mta-sts.example.com/.well-known/mta-sts.txt, which the server answers. The certificate must cover mta-sts.example.com.
The id is any value that changes when the policy changes. dns prints a timestamp; if a record is already published and you have not changed the policy, leave it as it is.
init configures a testing policy. The policy is served only when a mode is set and only for a verified domain. doctor checks both directions:
doctor finding | Cause |
|---|---|
no policy advertised, and this node serves none | Fine: no MTA-STS. |
this node would serve a <mode> policy and nothing points senders at it | Publish the TXT record, or unset the mode. |
… is published and this node serves no policy | Set a mode, or remove the record. |
… is published, and the domain is not verified, so no policy is served | Mark the domain verified. |
the <mode> policy names …, and this domain's MX also names … | Add the other MX hosts to [mta_sts] mx. |
TLS reporting
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@example.com"
A sending server that cannot negotiate TLS with yours has no other way to tell you. The reports arrive at tlsrpt@example.com and are filed by the server.
BIMI
Only for a domain that publishes a brand logo:
default._bimi.example.com. IN TXT "v=BIMI1; l=https://mail.example.com/.well-known/bimi/example.com/logo.svg; a=https://mail.example.com/.well-known/bimi/example.com/evidence.pem"
The a= part is there only when a mark certificate is published with the logo. doctor and the domain’s DNS check compare what is published with what the server would write, and warn when another BIMI record at the same name would stop receivers from showing any logo.
SRV records
_submissions._tcp.example.com. IN SRV 0 1 465 mail.example.com.
_submission._tcp.example.com. IN SRV 1 1 587 mail.example.com.
_imaps._tcp.example.com. IN SRV 0 1 993 mail.example.com.
_imap._tcp.example.com. IN SRV 1 1 143 mail.example.com.
_pop3s._tcp.example.com. IN SRV 0 1 995 mail.example.com.
_pop3._tcp.example.com. IN SRV 1 1 110 mail.example.com.
_jmap._tcp.example.com. IN SRV 0 1 443 mail.example.com.
A mail app that finds these needs only the email address. The TLS services have priority 0 and the STARTTLS services priority 1, so apps prefer TLS from the first byte. Nixt Mail uses the _jmap._tcp record to offer signing in over JMAP. The ports in the records are the default ports; if you move a listener, change the record.
Autoconfig and Autodiscover names (optional)
The server answers Mozilla autoconfig at autoconfig.<domain> and Microsoft Autodiscover at autodiscover.<domain>. To use them, add names that point at the server and include them in the certificate:
autoconfig.example.com. IN CNAME mail.example.com.
autodiscover.example.com. IN CNAME mail.example.com.
See Connecting mail apps.
Reverse DNS (PTR)
10.2.0.192.in-addr.arpa. IN PTR mail.example.com.
The PTR record belongs to whoever owns the address. Ask your ISP or hosting provider to set it; your domain’s DNS provider cannot. doctor checks that the host name resolves, that each address (up to two) has a PTR, and that the PTR name resolves back to the same address:
doctor finding | Verdict | What to do |
|---|---|---|
mail.example.com and its 1 address(es) confirm each other | ok | Nothing. |
192.0.2.10 has no PTR record | BAD | Ask the address owner for a PTR. If nobody will set one, send through a relay. |
192.0.2.10 points at host.provider.example, which does not resolve back to it | BAD | Have the PTR name your host, or give that name an address record. |
192.0.2.10 points at host.provider.example, not at mail.example.com | warn | Confirmed, so mail is not refused for it, but have the PTR name your host. |
mail.example.com resolves to no address | BAD | Publish an A or AAAA record. |
DANE (TLSA)
_25._tcp.mail.example.com. IN TLSA 3 1 1 <SHA-256 of the certificate's public key>
; DANE, and only worth publishing on a DNSSEC-signed zone (RFC 7672 §2): it
; pins the key the certificate now carries, so it has to be republished
; whenever that key changes or DANE-validating senders will refuse mail
DANE is optional and needs a DNS provider that offers the TLSA record type on a DNSSEC-signed zone. The record pins the key your certificate carries (usage 3, selector 1, matching type 1). ACME renewals keep the key; to change it safely, see TLS certificates.
init does not print this record, because the certificate you start with is often not the one you keep. When the certificate cannot be read, dns prints a note instead of a record: a wrong TLSA record refuses mail rather than degrading.
doctor finding | Verdict |
|---|---|
no _25._tcp.mail.example.com record, so nothing is promised about this host's key | ok |
… matches the certificate this node serves (1 record(s) published) | ok |
… N TLSA record(s) at …, and none matches the certificate this node serves | BAD: every DANE-validating sender is refusing your mail. |
… matches the certificate this node serves, and also pins a key this node no longer holds | warn: withdraw the old record after a finished rollover. |
… a key rollover is under way whose next key has no record there | warn: publish what dane status prints. |
Entering records at a DNS provider
Control panels differ, but the same mistakes come up:
- The host or name field usually takes only the part in front of your domain. Enter
_dmarc,mail,_mta-stsor<selector>r._domainkey, and@for the domain itself. A field that silently appends the domain turns_dmarc.example.cominto_dmarc.example.com.example.com, which resolves and means nothing. - Some panels need a setting before MX records take effect, such as choosing custom mail servers. Without it, mail keeps going where the previous setting pointed.
- Long TXT values: see DKIM above.
- SRV records are usually their own record type with separate fields for service, protocol, priority, weight, port and target.
- TLSA is not offered by every provider. Without it you cannot publish DANE; MTA-STS protects delivery to you instead.
- Switch on DNSSEC if your provider offers it. It lets other servers trust your records, is required for DANE, and lets “no such record” answers be cached.
After publishing
- Run
versealx-server doctorand fix what it reports. Records can take a while to appear. - When the ownership token is published, run
versealx-server admin post tenants/1/domains/example.com/verify. - Run
versealx-server dnsagain whenever you add a domain, rotate DKIM keys or change the certificate’s key.
Something unclear or out of date on this page? Tell us.