DNS Management

Domain registrar: Namecheap (registrar only — it just holds the domain registration and points the nameservers at Cloudflare). DNS records are managed in Cloudflare (account sean@immersive-app.com, free plan) since 2026-07-23 — see issue #505 for the migration. Email hosting (Namecheap Private Email, including the catch-all rule that forwards any-address@immersive-app.com → bonjour@immersive-app.com) is a separate paid service riding on the MX records below; it was unaffected by the move because the records travelled verbatim.

Proxy status (“orange cloud” vs “DNS only”): a proxied record makes Cloudflare answer with its own edge IPs and relay traffic to the origin (CDN, WAF, hides the origin IP). DNS only means Cloudflare merely publishes the record. Web records are proxied; every mail-related record must stay DNS only — proxying a mail record routes SMTP/verification traffic into Cloudflare’s HTTP proxy, which breaks it.

Web traffic (proxied)

Host Type Value Proxy
@ A 167.233.217.165 (Hetzner VM immersive-prod-01) Proxied
www A 167.233.217.165 (Hetzner VM immersive-prod-01) Proxied

What they mean: an A record maps a hostname to an IPv4 address. @ is the bare domain (immersive-app.com), www the usual alias; both point at the single Hetzner VM that runs the whole app (see kamal.md). Because they are proxied, the public internet only ever sees Cloudflare’s IPs — visitors reach a Cloudflare edge, which fetches from our origin.

Related settings that live with these records:

  • SSL/TLS mode: Full (strict) — Cloudflare-to-origin traffic is encrypted and the origin must present a valid certificate. Ours does: kamal-proxy serves a Let’s Encrypt cert, auto-renewed ~30 days before expiry via HTTP-01 (the challenge request passes through the proxy like any other request). If a renewal ever fails post-proxy, the fallback is a free Cloudflare origin certificate installed on the VM.
  • Origin firewall: the VM only accepts ports 80/443 from Cloudflare’s published IP ranges, so nobody can bypass the proxy by hitting the origin IP directly — see the “Origin firewall” section of kamal.md. SSH/deploys go to the origin IP and are unaffected.
  • Client IPs: behind the proxy the raw TCP peer is a Cloudflare edge, so the app uses the cloudflare-rails gem to restore the real visitor address in request.remote_ip — without it, Rack::Attack would throttle whole Cloudflare edges (i.e. everyone at once) instead of individual visitors, and Ahoy analytics would record edge IPs.

Email delivery — Namecheap Private Email (DNS only)

Host Type Priority Value
@ MX 10 mx1.privateemail.com
@ MX 10 mx2.privateemail.com

What they mean: MX (mail exchanger) records tell the world’s mail servers where to deliver mail addressed to …@immersive-app.com — here, Namecheap’s Private Email servers (two, same priority, for redundancy). The catch-all forwarding to bonjour@ is configured inside the Private Email service, not in DNS; DNS only gets the mail to their servers. (mail.immersive-app.com is the webmail URL — no extra DNS record needed.)

Email authentication (DNS only)

Host Type Value
@ TXT v=spf1 include:_spf.mailersend.net include:spf.privateemail.com ~all
default._domainkey TXT v=DKIM1;k=rsa;p=... (public key from MailerSend’s domain verification page)
_dmarc TXT v=DMARC1; p=none; rua=mailto:sean@immersive-app.com

What they mean — the three standards receiving servers use to decide whether mail claiming to be from immersive-app.com is genuine:

  • SPF lists which servers are allowed to send on the domain’s behalf — ours authorizes MailerSend (transactional app mail) and Private Email (human mail). Exactly one SPF record is permitted per domain: never add a second, merge new senders into this one, or delivery breaks for everything.
  • DKIM publishes the public key that matching mail is cryptographically signed with — receiving servers verify the signature to prove the message wasn’t forged or altered.
  • DMARC tells receivers what to do when SPF/DKIM checks fail. p=none is monitoring mode: nothing gets blocked, but aggregate reports are mailed to sean@. After a few weeks of clean reports, tighten to p=quarantine then p=reject to actively block spoofed mail.

MailerSend plumbing (DNS only — see docs/technical/production/mailersend.md)

Host Type Value
mlsend2._domainkey CNAME mlsend2._domainkey.mailersend.net.
mta CNAME mailersend.net. (return-path/bounce handling)

What they mean: both delegate a subdomain to MailerSend. The mlsend2._domainkey CNAME is MailerSend’s second DKIM key (they rotate/verify against it); mta is the bounce/return-path domain so undeliverable transactional mail routes back through MailerSend for bounce tracking. Caution from the migration: Cloudflare’s automatic import dropped the mlsend2._domainkey CNAME (underscore-prefixed CNAMEs are commonly missed) — it was re-added manually. Check both exist after any future DNS provider change, and keep them DNS only (the import also defaulted mta to proxied, which had to be switched off).

History

Until 2026-07-23 all records lived at Namecheap’s DNS with deliberately low (1 min) TTLs from the Heroku→Hetzner cutover (issue #288) — which made the Cloudflare migration propagate fast. Before that, the web records were CNAME/ALIAS to Heroku DNS targets — see docs/technical/production/heroku.md for the historical values.

References

  • MailerSend domain verification
  • docs/technical/production/mailersend.md — SMTP/webhook application config
  • docs/technical/production/heroku.md — historical Heroku DNS targets
  • docs/technical/production/kamal.md — current hosting setup, origin firewall
  • Issue #505 — Cloudflare migration record

This site uses Just the Docs, a documentation theme for Jekyll.