SPF, DKIM & DMARC for Ghost (Pro).
Ghost(Pro) is a managed publishing platform, and it sends your newsletters for you through its own managed Mailgun infrastructure — so unlike a self-hosted Ghost install, you never enter a Mailgun API key or region. Out of the box that mail leaves on Ghost's shared ghost.io sending domain, which is why subscribers see "newsletter@yourdomain.com via ghost.io." To send as your own domain you turn on a Custom sending domain (Publisher plan or higher): Ghost Admin generates a small set of per-account DNS records — a DKIM record and an SPF record on a dedicated sending subdomain — that you copy into your DNS, plus a DMARC record you add yourself (Ghost requires one to be present). There is no single shared SPF line to paste on your root; the records are specific to your account and shown inside Ghost Admin. Once they verify, Ghost signs newsletters as your domain, DKIM aligns, DMARC passes, and the "via ghost.io" tag disappears — after an automatic ~6-week reputation warm-up. The same records also authenticate Ghost's member and staff transactional email, which switches to your domain immediately.
Why authenticate Ghost (Pro)?
Setting up a custom sending domain is what moves your newsletter off Ghost's shared reputation and onto your own, and it's increasingly non-negotiable. Since February 2024, Gmail and Yahoo have required every bulk sender (roughly 5,000+ messages a day) to pass SPF, DKIM, and DMARC with alignment, and Microsoft extended similar enforcement to Outlook/Hotmail/Live in 2025 — and a newsletter is exactly the kind of bulk mail those rules target. Until you configure a custom sending domain, Ghost(Pro) sends every issue from ghost.io: recipients see the "via ghost.io" note, SPF and DKIM align to ghost.io rather than your domain, DMARC on your own domain gets no help from that mail, and the sending reputation you build is pooled with every other publication on Ghost's shared domain. A custom sending domain fixes the core of it — Ghost signs newsletters with DKIM on your sending subdomain (which aligns to your organizational domain), your From address becomes cryptographically yours, DMARC passes, and reputation accrues to you. One Ghost-specific nuance worth knowing: these records cover more than your newsletters. Member and staff transactional email — magic-link sign-in, paid-membership receipts, staff invites, comment notifications — also moves onto your custom sending domain, and it switches over immediately, with no warm-up. Newsletters are the opposite: Ghost warms them up gradually, so for roughly six weeks a fraction of each issue still leaves via ghost.io even though your transactional mail is already fully authenticated on your domain.
The SPF reality for Ghost (Pro)
Ghost(Pro) is a per-account sender, not a shared-include provider: there is no "include:ghost.io" or single SPF line every customer pastes on their root domain. Because Ghost runs its own managed Mailgun behind the scenes, the records it hands you in Ghost Admin are Mailgun-shaped and unique to your sending subdomain — a DKIM record plus an SPF TXT of v=spf1 include:mailgun.org ~all. The critical point is WHERE those go: on a dedicated sending subdomain that Ghost specifies (for example a send. or mail. host), never on your root domain's SPF. That matters for two reasons. First, your everyday mailbox mail — you@yourdomain.com on Google Workspace, Microsoft 365, or wherever — keeps its own root SPF and DKIM completely untouched; Ghost(Pro) does not host your inbox and its records don't collide with your mail provider's. Second, include:mailgun.org is heavy: verified live it expands to about five nested DNS lookups because a single line covers Mailgun's US and EU ranges. Kept on the sending subdomain, that weight sits in the subdomain's own SPF record and costs zero against your root domain's RFC 7208 ten-lookup budget — which is exactly why you must not copy include:mailgun.org onto your root. (Self-hosted Ghost is different: there you bring your own Mailgun account and enter its region, domain, and private API key under Settings → Email newsletter, then add the same style of records yourself. On Ghost(Pro), Ghost owns the Mailgun account and simply gives you DNS to publish.)
Step by step
- 1
Confirm your plan and custom domain
Custom sending domains require the Publisher plan or higher on Ghost(Pro), and the option only appears once you already have a custom domain connected to your publication (not the default yoursite.ghost.io URL). If you're on Starter, upgrade first; if you're still on the ghost.io URL, connect your custom domain before this option will show up.
- 2
Open Custom sending domain → Set up
Go to the Ghost(Pro) → Domain area within Ghost Admin, find the Custom sending domain section, and click Set up. Ghost derives a dedicated sending subdomain for your newsletters and shows the exact DNS records to publish — these are specific to your account, so copy them from this screen rather than from any generic tutorial.
- 3
Copy the DKIM and SPF records
Ghost displays the records to add: a DKIM record on a <selector>._domainkey host under your sending subdomain, and an SPF TXT (v=spf1 include:mailgun.org ~all) on that subdomain. Copy each host and value exactly — the DKIM selector and target are unique to your account and cannot be guessed.
- 4
Add the DKIM record on the sending subdomain
At your DNS host, create the DKIM record exactly as Ghost shows it. In most accounts this is a CNAME that delegates the key to Mailgun (so Ghost can rotate it for you); some accounts show a DKIM TXT (k=rsa; p=…) instead. Publish whichever Ghost gives you, unchanged, and don't switch its record type.
- 5
Add the SPF record on the sending subdomain
Add the SPF TXT (v=spf1 include:mailgun.org ~all) on the sending subdomain Ghost named — NOT on your root domain. If that subdomain somehow already has an SPF record, merge the include into it; never publish two SPF records on one host (that's a PermError). Your root SPF for your regular mailboxes stays exactly as it is.
- 6
Grey-cloud any Cloudflare CNAME
If your DNS is on Cloudflare and the DKIM record is a CNAME, set it to "DNS only" (grey cloud). An orange-cloud proxied CNAME won't resolve to Mailgun and Ghost's verification check will keep failing.
- 7
Publish your DMARC record (required)
Ghost doesn't create DMARC for you, but it does require one to be present to activate the custom sending domain — add a TXT record at _dmarc on your root domain. Ghost's own example is v=DMARC1; p=none; — add a reporting address to make it useful: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com. p=none is monitor-only, so nothing is affected while you confirm alignment. Keep exactly one _dmarc record for the whole domain.
- 8
Wait for green checkmarks in Ghost Admin
Back on the Custom sending domain screen, Ghost checks the records — a green checkmark means detected, a red exclamation mark means not yet. Propagation is typically 15 minutes to 24 hours; re-check the screen if a record is still red.
- 9
Send a test and expect the warm-up
Send yourself a test newsletter and open it via Show original: you want DKIM: PASS signed by your sending subdomain, SPF: PASS, and DMARC: PASS, with no "via ghost.io". Important: for roughly the first six weeks Ghost warms up your new subdomain by sending a fraction of each newsletter from ghost.io, so some recipients (and even your own test) may still show ghost.io during that window — that's expected, not a broken record. A member magic-link email, by contrast, already sends from your domain: transactional mail skips the warm-up.
Records to add
Ghost (Pro) generates the exact values in its setup wizard — these show the shape of what you'll add at your DNS host.
| Type | Host | Value |
|---|---|---|
| TXT | send | v=spf1 include:mailgun.org ~allSPF on the dedicated sending subdomain Ghost names (illustrative host — copy the exact subdomain from Ghost Admin). Goes on the subdomain, NOT your root SPF. include:mailgun.org is Mailgun's shared include, because Ghost runs Mailgun for you. |
| CNAME | krs._domainkey.send | krs._domainkey.<account>.dkim.mailgun.orgDKIM — delegated to Mailgun so keys auto-rotate. Illustrative: the selector (e.g. krs / k1 / a randomized token) and target are unique to your account and shown in Ghost Admin. Some accounts publish a DKIM TXT (k=rsa; p=…) instead — use whatever Ghost displays. |
| CNAME | email.send | mailgun.orgOptional open/click tracking on your domain. Add it only if Ghost Admin lists it; grey-cloud on Cloudflare. |
| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.comYou add this yourself — Ghost never creates it, but requires one to be present to activate the custom sending domain. One per domain, on the root; start at p=none. Ghost's own example uses the minimal v=DMARC1; p=none;. |
Keep exactly one SPF (v=spf1) TXT record on your root domain — merge every sender into it. Two SPF records is itself an error.
The 10-lookup budget
SPF is capped at a hard 10 DNS lookups — go over and it returns a permerror and stops validating everywhere. Here's what Ghost (Pro)'s setup costs against that budget.
Ghost (Pro)'s recommended setup adds 0 lookups — all 10 stay free for the senders that do need an include.
DKIM
DKIM is the load-bearing mechanism for Ghost(Pro) newsletters, because it's what aligns to your domain and carries the DMARC pass. When you enable the custom sending domain, Ghost (through its managed Mailgun) generates a per-account DKIM key on your sending subdomain and shows you the record to publish at a <selector>._domainkey host under that subdomain. In most accounts this is a CNAME that delegates the key back to Mailgun — because it's a CNAME rather than a static key you paste, Mailgun holds the private key and can rotate the published 2048-bit public key behind that selector without you ever editing DNS again. Some accounts instead show a static DKIM TXT (k=rsa; p=<long base64 public key>), which works identically but stays fixed until you regenerate it. Either way, outgoing newsletters are signed with d=<your-sending-subdomain>, and because relaxed DMARC alignment treats a subdomain and its parent as the same organizational domain, that DKIM signature aligns with your From address at yourdomain.com and satisfies DMARC. Copy the selector and value exactly as Ghost displays them (they're account-specific and can't be guessed), and if your DNS is on Cloudflare set a DKIM CNAME to DNS-only so it resolves. On Ghost(Pro) you never generate, store, or rotate the key yourself — that's Ghost's managed Mailgun's job.
DMARC
DMARC is a separate policy record that Ghost does not publish for you — and on Ghost(Pro) it's mandatory: Ghost requires a DMARC record on your domain to activate the custom sending domain, so this isn't an optional extra. Add it at your DNS host on your root domain, at _dmarc.yourdomain.com. Ghost's own help shows the minimal form v=DMARC1; p=none; but you should include a reporting address so you actually learn something: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com. p=none is monitor-only — it changes nothing about delivery while you use the aggregate (rua) reports to confirm that Ghost newsletters (and every other sender on your domain) are passing DKIM aligned to your domain. Because a DMARC record on the root already governs subdomains through the organizational-domain rule, this one record covers your sending subdomain too — don't add a second _dmarc on the subdomain. Keep exactly one _dmarc for the whole domain no matter how many services you send through. Once reports show Ghost as a consistent, aligned source over a week or two — and remembering the ~6-week warm-up means ghost.io will also appear as a source during that period — tighten the policy from p=none to p=quarantine and eventually p=reject, which is what actually stops attackers spoofing your domain.
Check it actually worked
Don't rely on Ghost's green checkmarks alone — they confirm the records resolve, not that a real newsletter authenticates. Send yourself a test issue, open it in Gmail, and choose ⋮ → Show original: you want DKIM: PASS signed by your sending subdomain (not ghost.io), SPF: PASS, and DMARC: PASS, with the "via ghost.io" note gone from the sender line. The one Ghost-specific caveat: during the roughly six-week reputation warm-up, Ghost deliberately still sends a portion of each newsletter from ghost.io, so an early test — or reports from some subscribers — showing ghost.io is expected behavior, not a misconfiguration, and it resolves itself as the warm-up completes. Test with a real newsletter, not a magic-link email: transactional mail moves onto your sending domain immediately, so it will pass before your newsletters finish warming up. Run your sending subdomain through Qualisend's domain health check to confirm the DKIM, SPF, and DMARC records all resolve cleanly, and once DMARC aggregate reports start arriving, drop one into the DMARC report analyzer — your Ghost/Mailgun sending subdomain should show up as an aligned, passing source (alongside ghost.io while warm-up is still in progress).
Common gotchas
- Coverage
Ghost(Pro) is not self-hosted Ghost. On Ghost(Pro) you never enter a Mailgun API key, region, or domain — Ghost owns the Mailgun account and configures it for you. Those Settings → Email newsletter Mailgun fields belong to self-hosted installs; on Ghost(Pro) you use the Custom sending domain flow instead, and DNS records are the only thing you touch.
- DNS setup
The feature is gated: Custom sending domains need the Publisher plan or higher AND a custom domain already connected to your publication. On Starter, or while you're still on a yoursite.ghost.io URL, the Set up button simply won't be there.
- Coverage
The ~6-week warm-up is normal. After your records verify, Ghost still sends a fraction of each newsletter from ghost.io while it builds reputation on your new subdomain — so 'via ghost.io' lingering for weeks (and appearing in early tests) is expected, not a broken record. Don't re-do your DNS chasing it.
- Coverage
It authenticates your transactional mail too, not just newsletters. Member and staff email — magic-link sign-in, membership receipts, staff invites, comment notifications — also switches to your custom sending domain, and unlike newsletters it does so immediately, with no warm-up. So a magic-link email will show your own domain right away; that's expected — but it doesn't mean your newsletters have finished migrating. Gauge newsletter migration on a real newsletter, not a login email.
- Coverage
Ghost(Pro) doesn't host your inbox. Your day-to-day you@yourdomain.com mail lives on Google Workspace / Microsoft 365 / etc. with its own root SPF, DKIM, and DMARC. Ghost's records go on a separate sending subdomain — adding them must not touch or overwrite your mail provider's root SPF or DKIM.
- Breaks auth
Never put include:mailgun.org on your ROOT SPF. It belongs only on the sending subdomain Ghost names. On the root it does nothing for your newsletter alignment and burns about five of your ten SPF lookups (it covers Mailgun's US and EU ranges) — keep it off the root entirely.
- DNS setup
Cloudflare proxy breaks the DKIM CNAME: set it to 'DNS only' (grey cloud); an orange-cloud proxied CNAME won't resolve to Mailgun and Ghost's verification stays red. And watch registrar host-doubling — enter just the label Ghost shows (the _domainkey selector under your subdomain), not the full domain, if your panel auto-appends it.
Build your SPF record
Ghost (Pro) doesn't need an SPF include: on your root domain — use the generator to assemble one clean record for your other senders, and keep it to a single line.
Sending sources
Search for each platform you send email through and tick it.
Search for your email platform above, or .
This domain's own servers
Authorize the domain itself, if it sends mail directly (not through a platform above).
Other senders & IPs
Anything not in the list — another provider's SPF host, or specific IP addresses.
We add the include: prefix — enter the hostname your provider documents.
Policy for everyone else
What receivers should do with mail from any server not listed above (the all mechanism).
No senders yet, so every message would hit the ~all policy. Add the platforms you send through in step 1.
- Publish it as a TXT record at your root domain — host @ (the bare domain), value the full string above.
- Keep only one SPF record per domain. Merge every sending source into this single line — a second TXT record starting v=spf1 makes both invalid.
- Stay at or under 10 DNS lookups. Each include:, a and mx counts, and an include can trigger more lookups inside itself — ip4: and ip6: are free.
Authentication published? The next step is sending to a clean, verified list.
Verify a listGhost (Pro) SPF — FAQ
Related reading
Once it's published, confirm everything resolves with the domain health check, then read who's sending as you with the DMARC report analyzer. Browse all sending sources in the generator. Authentication is only half of deliverability, though — a listed sending IP or domain still lands you in spam no matter how clean your SPF is, so it's worth watching the blacklists with blacklist monitoring.
Authenticated — now keep the list clean
Passing SPF, DKIM, and DMARC gets you to the inbox; a clean list keeps you there. Verify yours — start free with 100 credits, no card required.