Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DNS setup

Two independent sets of records matter to a SithBit operator: the classic mail records that let the rest of the internet find and trust your server — and let your users’ mail clients locate its POP/IMAP/ submission ports — and the SithBit-specific record that proves you control a domain before it is authorized on-chain.

Throughout, example.com is the mail domain (the part after @) and mail.example.com is the host running sithbitd.

Receiving mail: MX

example.com.        MX  10  mail.example.com.
mail.example.com.   A       203.0.113.25

The MX target must be an A/AAAA name, not a CNAME. Add example.com to [smtp] local_domains in sithbitd.toml so the MX listener accepts mail for it, and set [smtp] hostname (and [spooler] hostname) to mail.example.com so the EHLO greeting matches DNS — many receivers score a mismatch as spam.

One server may host several mail domains: point each domain’s MX at the same host and list them all — local_domains = ["example.com", "example.net"]. Each domain needs its own on-chain authorization (below) under the same authority key, its own DKIM record and [[spooler.dkim]] entry, and the daemon warns at startup about any listed domain whose on-chain authority doesn’t match (see the configuration reference).

Inbound sender checks (sender_auth = "spf", the default, or "dmarc-lite") need nothing from your DNS; they query the sender’s records.

Sending mail: SPF, DKIM, DMARC, PTR

Receivers judge your outbound mail by these records; without them, expect the spam folder.

SPF — authorize your relay host to send for the domain:

example.com.  TXT  "v=spf1 mx -all"

mx authorizes whatever your MX records point at; add ip4:/ip6: mechanisms if outbound mail leaves from other addresses, or include: your smarthost provider when [spooler.smarthost] routes mail through one.

DKIMsithbitd signs authenticated submissions (rsa-sha256, RFC 6376) when [spooler.dkim] is configured. Generate a key and publish its public half at {selector}._domainkey.{domain}:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out dkim.pem
openssl rsa -in dkim.pem -pubout -outform DER | openssl base64 -A
[spooler.dkim]
domain = "example.com"
selector = "mail"
key_file = "dkim.pem"     # PEM, PKCS#8 or PKCS#1
mail._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p=<the base64 output>"

Only authenticated submission is signed — mail arriving at the MX from other servers relays unsigned, which is correct: it isn’t yours.

DMARC — tell receivers what to do when SPF/DKIM fail, and where to send reports:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:[email protected]"

Add a ruf= address (and fo=1 to request a report on any failure) to also receive per-message failure/forensic reports — a copy of each failing message, so point it at a mailbox you control:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; fo=1; rua=mailto:[email protected]; ruf=mailto:[email protected]"

Start with p=none while you confirm SPF and DKIM pass, then tighten.

The rua= address can be your own SithBit deployment — other operators’ aggregate reports about example.com are how you confirm your SPF and DKIM actually align in the wild. Point the record at your postmaster mailbox:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:[email protected]"

Two settings pair up on this receiving side, both off by default (rows in the configuration reference). [smtp] postmaster_wallet names the wallet that mail for bare postmaster / postmaster@<local-domain> is delivered to, exempting it from the frombox/postage gate — without it an external reporter, who never holds a prepaid frombox, is refused like any other stranger. And [spooler.dmarc_rua_ingest] parses each delivered report (the message still lands in the mailbox as ordinary mail) and stores the result as JSON for the account API’s admin reader, GET /v1/admin/dmarc-reports — see account-api for the routes and the conformance appendix for exactly what ingestion does and doesn’t do with the data.

MTA-STS — downgrade-resistant TLS for server-to-server delivery (RFC 8461). For outbound mail there is nothing to configure: sithbitd‘s relay discovers and honors recipients’ published policies automatically (the mta_sts switch in the [spooler] reference). To protect mail inbound to your own domain, publish the discovery record and serve the policy — domain-sithbit publishes the policy for you from its [mta_sts] config section (see domain-sithbit: publishing the MTA-STS policy):

_mta-sts.example.com.  TXT  "v=STSv1; id=20260716T000000"

Senders fetch the policy as https://mta-sts.example.com/.well-known/mta-sts.txt, so point an mta-sts.example.com A (or CNAME) record at your domain-sithbit deployment, fronted by a TLS proxy holding a certificate for that hostname; the service serves the configured policy at that well-known path:

version: STSv1
mode: enforce
mx: mail.example.com
max_age: 604800

The mx patterns must cover every host your MX records name, and the TXT record’s id must change whenever the policy content does — bump it every time you edit the [mta_sts] section, since senders cache the policy by that id. Start with mode: testing (the config default) while you confirm your MX serves STARTTLS with a certificate valid for its hostname, then move to enforce.

DANE — DNSSEC-pinned TLS for server-to-server delivery (RFC 7672), the stronger sibling of MTA-STS. For outbound mail there is nothing to configure: sithbitd‘s relay looks up and honors recipient MX hosts’ DNSSEC-validated TLSA records automatically (the dane switch in the [spooler] reference), preferring them over MTA-STS. To protect mail inbound to your own domain, your zone must be DNSSEC-signed (unsigned TLSA records are ignored by every DANE sender); then publish a TLSA record for each MX host:

_25._tcp.mail.example.com.  TLSA  3 1 1 <sha256-of-the-SPKI>

3 1 1 — DANE-EE, SPKI selector, SHA-256 — is the recommended form: it pins the certificate’s public key, so ordinary renewals that keep the key don’t touch DNS. Compute the digest from your certificate:

openssl x509 -in fullchain.pem -pubkey -noout \
  | openssl pkey -pubin -outform DER | sha256sum

When rotating to a new key, publish the new record alongside the old one, swap the certificate, then drop the old record (senders accept a match against any published record). If your certificate chain rotates keys on every renewal, pin the issuing CA instead (2 1 1, DANE-TA) — but note the presented chain must then include that CA certificate.

A signed domain that receives mail on the implicit-A fallback — no MX record, mail delivered to the domain host itself — gets DANE too: DNSSEC proves the absence of the MX record to senders (SithBit’s relay validates the denial from the negative answer’s SOA), so publish the TLSA record at the domain’s own name, no MX required:

_25._tcp.example.com.  TLSA  3 1 1 <sha256-of-the-SPKI>

TLS-RPT — feedback on how MTA-STS and DANE hold up in practice (RFC 8460). Publishing a TLSRPT record asks sending MTAs to aggregate the TLS outcomes of their deliveries to your domain — successes, STARTTLS stripping, certificate failures — and report them daily to an address you name:

_smtp._tls.example.com.  TXT  "v=TLSRPTv1; rua=mailto:[email protected]"

(https: report targets are also allowed.) This is how a downgrade attack against your domain becomes visible instead of just delaying senders’ mail. On the sending side there is one switch: with [spooler.tlsrpt] enabled, sithbitd records its own outbound TLS results and sends these reports to every recipient domain that publishes the record — see the conformance appendix for exactly what is recorded and reported.

PTR — the reverse record for your outbound IP must resolve to your EHLO hostname (203.0.113.25 → mail.example.com). This is set with your hosting provider, not in your zone; several large receivers refuse mail from IPs without a matching PTR.

Client access: POP, IMAP, and submission SRV records (RFC 6186)

MX tells other servers where to deliver mail; these SRV records tell your users’ mail clients which host and port to reach for POP3, IMAP, and message submission — so a client that knows only an address and password can configure the rest. RFC 6186 defines the labels and RFC 8314 adds the implicit-TLS variants clients should prefer; publish only the ones matching listeners your sithbitd stack actually runs.

Implicit TLS (preferred — RFC 8314). SithBit’s production posture is TLS-on-connect on the standard secure ports, matching the [mail_hosts] defaults:

_imaps._tcp.example.com.        SRV  0 1 993 mail.example.com.
_pop3s._tcp.example.com.        SRV  0 1 995 mail.example.com.
_submissions._tcp.example.com.  SRV  0 1 465 mail.example.com.

STARTTLS (secondary). If you also run the opportunistic-upgrade listeners, advertise them at a higher priority number (lower preference) so compliant clients still reach for implicit TLS first. The shipped [mail_hosts] submission default is now implicit TLS on 465 (per RFC 8314); STARTTLS on 587 is an opt-in you configure and advertise only if you run that listener:

_imap._tcp.example.com.        SRV  10 1 143 mail.example.com.
_pop3._tcp.example.com.        SRV  10 1 110 mail.example.com.
_submission._tcp.example.com.  SRV  10 1 587 mail.example.com.

The four fields after SRV are RFC 2782 priority weight port target: the lowest priority wins, weight load-balances ties among equal priorities, and — as with MX — the target must be an A/AAAA host, never a CNAME. Point it at the same mail.example.com your other records use.

Advertising only what you serve

Publish a record only for a protocol you actually run. To tell clients a protocol is not offered — e.g. an IMAP-only server with no POP — publish a single record with target . and port 0:

_pop3s._tcp.example.com.  SRV  0 0 0 .

SRV is advisory and one of three autoconfiguration paths: a client that ignores it falls back to the autoconfig/autodiscover documents domain-sithbit serves, or to manual setup (Thunderbird, Outlook) — keep the ports and transport security here consistent with what those advertise. SithBit clients can also skip DNS for access-server discovery entirely and resolve authorized POP/IMAP nodes over the DHT (see decentralized service discovery).

The autoconfig and autodiscover hostnames

The document fallback above only works if the wizard can reach domain-sithbit at the well-known hostnames it probes: Thunderbird fetches https://autoconfig.<domain>/mail/config-v1.1.xml (and, as a second try, /.well-known/autoconfig/mail/config-v1.1.xml on the mail domain itself), while Outlook posts to https://autodiscover.<domain>/autodiscover/autodiscover.xml. Publish both names, pointed at the host where your domain-sithbit instance is reachable — a plain A/AAAA or, since these are HTTP hosts (not SRV targets), a CNAME is fine:

autoconfig.example.com.    CNAME  mail.example.com.
autodiscover.example.com.  CNAME  mail.example.com.

The wizard fetches over HTTPS, so the service’s TLS certificate must cover these names too (add them as SANs, or use a wildcard). The documents themselves are rendered from [mail_hosts] — no per-domain zone content beyond the two records.

Authorizing a domain on-chain

Before wallets can register aliases and mailboxes under @example.com, the domain must exist as an on-chain Domain account — created by the postoffice’s delegate for a claimed authority key. The domain-sithbit service automates the claim with a DNS proof:

  1. The domain owner generates (or picks) an ed25519 keypair and publishes its public key, base58-encoded, as a TXT record:

    _solana.authority.example.com.  TXT  "<base58 ed25519 public key>"
    
  2. POST /domain on the domain-sithbit service with the domain name as the body. The service resolves that TXT record, validates the key, and — signing with its configured delegate key — submits CreateDomain naming the key as the domain’s authority.

  3. GET on the same service answers what the TXT record currently claims, which is useful for checking propagation before posting.

Operational notes:

  • Without a configured delegate_key_file, POST /domain replies 503 — DNS lookups still work. See the configuration reference.
  • The TXT lookup goes to a public resolver, so freshly published records may take a propagation delay to become visible.
  • The authority key is a real signing key — the mail server submits SendMail with it — so store it like a wallet, not like a DNS token. The TXT record can be removed after authorization; the on-chain account is what matters from then on.
  • The same authority key can claim any number of domains: publish the same public key in each domain’s TXT record and POST each claim. A multi-domain server authorizes every domain it serves under its one gateway key this way.

See Domains for what a domain account contains and the CLI flows the delegate holder can drive by hand.