--- title: "Email & DNS Setup — Domains, Mailboxes & Records" type: area status: active created: "2026-10-11 14:59" updated: "2026-09-26" tags: - email - domains - mailboxes - records - dns - cloudflare - ses - purelymail - reference aliases: - email-setup - dns-and-email-reference modified: "2026-10-11 14:59" --- # [[Email & DNS Setup — Domains, Mailboxes & Records]] > **Single reference for how email + DNS works across all domains.** Written 2026-10-11. > Verify any record with: `host -t MX ` / `host -t TXT `. > Secrets are **not** in Obsidian — see "Credentials" below. --- ## 1. Architecture (three layers) Email is split so each concern uses the right tool — **mailboxes** and **sending** are deliberately separate (reputation isolation): ``` INBOUND → Cloudflare DNS (MX) → PurelyMail (mailboxes) → forward → Gmail OUTBOUND → Amazon SES (verified, SPF+DKIM signed) ← websites / apps DNS → Cloudflare (authoritative for all domains; also holds site A records) ``` | Layer | Provider | Cost | Role | |---|---|---|---| | **DNS** | **Cloudflare** (authoritative NS) | $0 | All DNS: A, MX, SPF, DKIM, DMARC | | **Inbound mailboxes** | **PurelyMail** (`mailserver.purelymail.com`) | ~US$10/yr flat, **unlimited domains** | Real domain mailboxes + forwarding | | **Reading mail** | **Gmail** (`samuelrolfe@gmail.com`) | $0 | PurelyMail forwards everything into Gmail | | **Outbound (websites)** | **Amazon SES** (ap-southeast-2) | ~$0 at low volume | Transactional sending, DKIM-signed | **Why this shape:** inbound uses PurelyMail (managed, so no residential-IP blacklist risk), outbound uses SES (deliverability + reputation isolation from the inbox). Neither uses a local home IP for mail. --- ## 2. Domains | Domain | Registrar | DNS (NS) | Site hosted | Status | |---|---|---|---|---| | **audasmedia.com.au** | Squarespace/CrazyDomains | Cloudflare (`jo`/`osmar`) | CMS sites still on **InMotion** (origin `173.231.229.92`), proxied via Cloudflare | Email ✅ live; site migration pending | | **where-woof.com** | Squarespace/CrazyDomains | Cloudflare (`dane`/`barbara`) | **.13** (behind Caddy .35 → `.13:3020`), A → `144.6.86.11` | Live ✅ | | **kontra.day** | **Cloudflare** (registered here) | Cloudflare (`barbara`/`dane`) | **.13** (planned) | Being built (Go + htmx); email + A records not yet added | | ~~kontra.news~~ | — | — | — | ❌ **Expired** — never delegated at registry; replaced by kontra.day | --- ## 3. Email accounts / mailboxes | Address | Provider | Delivers to | Purpose | |---|---|---|---| | `sam@audasmedia.com.au` | PurelyMail | forwards → `samuelrolfe@gmail.com` | Primary personal/domain address | | `hello@where-woof.com` | PurelyMail | forwards → `samuelrolfe@gmail.com` | where-woof enquiries | | `hello@kontra.day` | PurelyMail | *planned* → `samuelrolfe@gmail.com` | kontra enquiries | | *(catch-all)* | PurelyMail | → `samuelrolfe@gmail.com` | Catches any address at the domain | **Sending:** Gmail "Send mail as" (via PurelyMail SMTP) for personal replies; **Amazon SES** for websites/apps. --- ## 4. DNS records per domain All three use the same Cloudflare pattern. **All mail records are DNS-only (grey cloud).** ### audasmedia.com.au | Type | Name | Value | |---|---|---| | NS | `@` | `jo.ns.cloudflare.com`, `osmar.ns.cloudflare.com` | | **MX** | `@` | `10 mailserver.purelymail.com` | | TXT | `@` | `v=spf1 include:_spf.purelymail.com include:amazonses.com ~all` | | CNAME | `purelymail1._domainkey` | `key1.dkimroot.purelymail.com` | | CNAME | `purelymail2._domainkey` | `key2.dkimroot.purelymail.com` | | CNAME | `purelymail3._domainkey` | `key3.dkimroot.purelymail.com` | | CNAME | `_dmarc` | `dmarcroot.purelymail.com` | | CNAME | `autoconfig` | `autoconfig.purelymail.com` | | SRV | `_autodiscover._tcp` | `autodiscover.purelymail.com` (0 0 443) | | A | `@` | `173.231.229.92` (InMotion origin, **Cloudflare-proxied**) | ### where-woof.com | Type | Name | Value | |---|---|---| | NS | `@` | `dane.ns.cloudflare.com`, `barbara.ns.cloudflare.com` | | **MX** | `@` | `10 mailserver.purelymail.com` | | TXT | `@` | `v=spf1 include:_spf.purelymail.com include:amazonses.com ~all` | | TXT | `@` | `purelymail_ownership_proof=...` (PurelyMail verification) | | CNAME | `purelymail1/2/3._domainkey` | `key1/2/3.dkimroot.purelymail.com` | | CNAME | `_dmarc` | `dmarcroot.purelymail.com` | | CNAME | `autoconfig` | `autoconfig.purelymail.com` | | SRV | `_autodiscover._tcp` | `autodiscover.purelymail.com` | | A | `@`, `www`, `admin` | `144.6.86.11` (**DNS-only** — home static IP) | ### kontra.day ⏳ *(not yet configured)* Planned, identical to where-woof once PurelyMail ownership proof is added: MX → `mailserver.purelymail.com` · SPF (PurelyMail + SES) · DKIM ×3 · DMARC · ownership TXT · A `@`/`www` → `144.6.86.11` (DNS-only). --- ## 5. Amazon SES (outbound) | Item | Detail | |---|---| | **Region** | `ap-southeast-2` (Sydney) | | **Verified identities** | `audasmedia.com.au`, `where-woof.com` | | **Sending direction** | Websites/apps (transactional only — not marketing) | | **SMTP endpoint** | `email-smtp.ap-southeast-2.amazonaws.com` port **587** (STARTTLS) | | **SMTP IAM user** | `ses-smtp-user.20260903-152339` (permission: `ses:SendRawEmail`) | | **MAIL FROM** | Default (`amazonses.com`) — DMARC still passes via DKIM alignment | | **Production access** | Requested 2026-09-03 (transactional) — **verify current status in SES console** | | **Sandbox note** | Until production access is granted, SES only sends to *verified* addresses | **Handoff for web builders:** SMTP host/port above; sender = the domain address (e.g. `hello@where-woof.com`); use SES (not PurelyMail SMTP) for site mail. --- ## 6. Websites & domain routing | Domain | Served from | Route | |---|---|---| | **where-woof.com** (+www, admin.where-woof.com) | `.13` container (`.13:3020`), Postgres `wherewoof-db`, MinIO | Caddy (.35) `reverse_proxy 192.168.20.13:3020` | | **audasmedia.com.au** + CMS sites | InMotion VPS (`173.231.229.92`) — *to be migrated to .13* | Cloudflare-proxied A → InMotion | | **kontra.day** | `.13` (planned, Go + htmx) | Caddy route to be added (port TBD, e.g. 3050) | | `*.lab.audasmedia.com.au` | Home services on `.13`/`.35` | Caddy (.35), wildcard A → `144.6.86.11` | **Caddy** on `.35` is the single reverse proxy for all public sites + `.lab` services (basic-auth on private ones). --- ## 7. Credentials (NOT in this note) | What | Where | |---|---| | AWS keys + SES SMTP creds | `/home/sam/inmotionhosting_S3_email/aws-credentials.local` (600, on .27) and `.13:/home/sam/.aws-credentials.local` | | Garage admin/metrics tokens | `.13:/home/sam/Docker/Containers/family-home-lab/garage/garage.toml` + `.env` | | PurelyMail account | PurelyMail dashboard login | | Cloudflare account | Cloudflare dashboard login | > ⚠️ Obsidian is backed up (cloud) — **never put secrets in vault notes.** --- ## 8. Key gotchas - **MX must point at PurelyMail** (`mailserver.purelymail.com`), not a local IP — residential IPs get blacklisted for mail. - **Cloudflare Email Routing and an external provider (PurelyMail) conflict** — Email Routing must be **disabled** on a domain before pointing MX at PurelyMail (MX records are locked while Email Routing is on). - **SPF must merge providers**: one TXT listing `_spf.purelymail.com` *and* `amazonses.com`. - **DMARC passes via DKIM** even with default MAIL FROM. - **Add kontra.day to PurelyMail first** to get its unique ownership proof, then add records in Cloudflare. - Garage S3 (local object store) is **separate** from AWS S3 offsite — see [[Backup System — Borg, Kopia & Restic]]. --- ## Related notes - [[Migration Plan — InMotion to Local + AWS Offsite]] - [[Phase 2 — Email]] - [[Cloudflare Record Set — audasmedia.com.au]] - [[audasmedia.com.au — DNS Baseline]] - [[Backup System — Borg, Kopia & Restic]] - [[Error Tracking]] --- *Draft — review and move to an area/project once verified.*