Ghost CMS Confirmation Email Link Goes to 404: Causes and Fixes
Quick answer: Ghost confirmation email links go to a 404 for five main reasons: the link expired (Ghost's 10-minute default), a broken welcome page route, a URL mismatch between your config and routes.yaml, a Cloudflare or proxy stripping the token, or the member portal not being enabled. Each fix takes under 10 minutes.

You've just launched your Ghost newsletter. Someone subscribes — excited, ready to read. They open the confirmation email, click the link, and land on a 404 page. They're gone. Probably for good.
This happens more than you'd think. On the Ghost forum, a site owner recently reported over 10 subscribers hitting this exact wall after their first month live. Their subscriptions were registering fine on the backend. The email just sent people to nowhere. That's the worst kind of broken — invisible to you, fatal to your reader.
There are five distinct causes. Most take five minutes to fix once you know which one you're dealing with.
Why does the Ghost confirmation email link go to a 404?
Before jumping to fixes, it helps to understand what that confirmation link actually does. When someone subscribes on Ghost, the platform sends a "magic link" — a one-time URL containing a signed token. Clicking it confirms the subscriber's email and redirects them, usually to a welcome page or your homepage.
A 404 means one of two things: the URL itself is invalid, or the page it points to doesn't exist. Here are the five causes that account for nearly every case:
How do I fix the "10-minute expiry" problem on Ghost confirmation emails?
Ghost's magic link tokens expire after 10 minutes by default. If a subscriber doesn't open their email immediately — which most don't — the link is dead before they click it. This is the most common cause of confirmation 404s on self-hosted Ghost.
The fix for self-hosted installations is to increase the token expiry in Ghost's magic-link module:
- SSH into your server and navigate to your Ghost install directory
- Find the magic-link module:
find /var/www/ghost -name "index.js" -path "*/magic-link/*" - Open that file and search for
expiresIn: '10m'— it appears four times - Change all four instances to
expiresIn: '1d' - Restart Ghost:
ghost restart
# Find the magic-link module
find /var/www/ghost -name "index.js" -path "*/magic-link/*"
# Edit expiry (change all 4 occurrences of '10m' to '1d')
nano /var/www/ghost/versions/CURRENT/node_modules/@tryghost/magic-link/index.js
# Restart Ghost
cd /var/www/ghost && ghost restartImportant: This change gets overwritten when you update Ghost. Re-apply it after every major update. Ghost Pro users can't modify core files — contact Ghost support to request an extended expiry or consider self-hosting for more control.
What is the welcome page route and why does it cause 404 errors?
After confirming their email, Ghost redirects new subscribers to a "welcome page." If that page doesn't exist or has a broken slug, they land on a 404 — even though the email confirmation itself succeeded.
Check and fix this in Ghost Admin:
- Go to Settings → Tiers
- Click on the tier your subscriber joined (Free or a paid tier)
- Find the Welcome page field
- Either clear it (redirects to homepage) or set it to a valid existing page slug
The tricky part: the subscriber does get confirmed in your database even when they hit a 404 welcome page. You can verify in Members → All members. Their subscription is real — only the landing experience is broken.
This is also worth checking if you've ever deleted or renamed a page that was set as a welcome destination. Ghost doesn't auto-update this field.
How do I check if a URL mismatch is causing subscriber 404s in Ghost?
Ghost embeds your site's URL in every magic link. If the URL in your config.production.json doesn't match what's actually serving your site, the token still works but the domain resolves wrong — often to your old domain or an IP address.
This is common after:
- Changing your domain (covered in detail in our guide to updating your Ghost URL)
- Migrating to a new server
- Adding www vs non-www
- Switching between HTTP and HTTPS
Check your current URL config:
cat /var/www/ghost/config.production.json | grep urlIf the URL there differs from your actual domain, update it and restart:
ghost config url https://yourdomain.com
ghost restartIf you recently changed your domain and broke admin access, see our fix guide for Ghost admin login not working after a URL change — the root cause is the same.
Can Cloudflare or a reverse proxy break Ghost confirmation links?
Yes. This one is subtle. Cloudflare's click-tracking or security features can rewrite URLs in emails, stripping or mangling the authentication token. The link looks fine in the email but fails when clicked because the token is malformed or missing.
Also, some Cloudflare page rules or firewall settings block requests to Ghost's /members/api/ endpoints — returning a 404 or 403 that looks like a missing page.
Diagnose this by testing the confirmation flow with Cloudflare in Development Mode (bypasses most caching and rules). If subscriptions start working, the issue is a Cloudflare rule or setting.
Common fixes:
- Disable Cloudflare email link rewriting (Scrape Shield → Email Address Obfuscation — turn off)
- Add a firewall rule to allow all traffic to
/members/* - If using Cloudflare proxied DNS, verify your SSL/TLS mode is set to Full (Strict) — see our guide on Cloudflare SSL for Ghost
- Check that Mailgun click tracking isn't enabled if your domain uses HTTP-only tracking — Mailgun requires HTTPS for tracked links
Caching issues can also cause stale 404 responses. Our Ghost Cloudflare caching guide covers which paths to exclude from cache — /members/* should always bypass.
How do I check if the Ghost Portal is configured correctly for member subscriptions?
Ghost Portal is the built-in membership UI — the popup that handles sign-ups, sign-ins, and subscription management. If Portal isn't enabled or is misconfigured, links like /members/ and #/portal/ return 404s.
Check in Ghost Admin:
- Go to Settings → Membership
- Confirm memberships are enabled for your site
- Go to Settings → Portal and verify Portal is active
For themes with custom sign-in or sign-up pages, the routes must be defined in routes.yaml. A missing or misconfigured route causes exactly the 404-on-signin pattern. Example configuration:
routes:
/signup/:
controller: channel
filter: 'tag:signup'
/signin/:
controller: channel
collections:
/: {permalink: /{slug}/}
taxonomies:
tag: /tag/{slug}/
author: /author/{slug}/After editing routes.yaml, always restart Ghost — changes don't hot-reload:
cd /var/www/ghost && ghost restartIf Ghost itself won't restart, check our troubleshooting guide for Ghost restart not working before proceeding.
How can I test the full subscriber confirmation flow myself?
Before declaring the fix done, run the full flow with a fresh test email:
- Open your site in an incognito window
- Subscribe with a real email you control (Gmail, Fastmail — avoid plus aliases with some providers)
- Wait for the confirmation email — usually under 2 minutes
- Click the link immediately and verify it lands correctly
- Then wait 15+ minutes and try with another test email to confirm the expiry fix worked
Also check Settings → Email → Mailgun (or your configured email provider) for bounce or delivery errors. If the email arrives but the link fails, the provider isn't the issue. If no email arrives at all, the problem is email delivery, not the link itself.
What if subscribers are confirmed but still hitting 404 after clicking?
Check your Ghost logs for the specific endpoint that's failing:
ghost logLook for requests to /members/api/send-magic-link/ or /members/?token=. A 404 on /members/api/ usually means a Nginx or Apache config problem — the proxy isn't passing those paths to Ghost.
Example Nginx fix — ensure Ghost's members API paths are proxied:
location /members/ {
proxy_pass http://127.0.0.1:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}After editing Nginx config, reload it without downtime:
nginx -t && systemctl reload nginxIf your server is running low on memory and crashing Ghost processes, subscribers won't get confirmation emails at all — check our fix for out-of-memory crashes on 1GB Ghost servers.
Quick diagnostic checklist
| Symptom | Most likely cause | Fix |
|---|---|---|
| Link works immediately, fails 10+ min later | Token expiry | Change expiresIn to 1d |
| Email confirmed in Members, 404 on redirect | Broken welcome page | Fix or clear the welcome page in Tiers settings |
| Started after domain change | URL mismatch in config | Run ghost config url |
| Works without Cloudflare, fails with it | Cloudflare rule/proxy | Allow /members/*, disable email obfuscation |
| /members/ path returns 404 entirely | Portal disabled or Nginx config | Enable Portal or fix proxy config |
| No confirmation email arrives at all | Email delivery failure | Check Mailgun logs or switch providers |
Related Ghost Guides
- Ghost CMS Restart Not Working — needed after editing core files or routes.yaml
- Ghost Admin Login Not Working After URL Change — same URL mismatch root cause
- Ghost CMS Mailgun Alternatives — if email delivery itself is the issue
- Cloudflare SSL for Ghost — proxy and SSL config that affects member links
- Restrict Content to Specific Membership Tiers — tier and welcome page setup
- How to Update Your Ghost URL/Domain — full migration process
Frequently Asked Questions
Why do some subscribers get a 404 but others don't?
Usually the token expiry. Subscribers who click within 10 minutes succeed; those who open their email later hit the expired link. This is intermittent by design, which makes it hard to catch in testing.
Does the subscriber still get added even when the confirmation link gives a 404?
It depends on the cause. If the token expired, the subscription is not confirmed — they'll appear as "unconfirmed" in Ghost Members. If the 404 is just on the welcome page redirect, the subscription is confirmed and they're in your list.
How do I resend a confirmation email in Ghost?
Ghost doesn't have a built-in "resend confirmation" button in the admin UI. The subscriber needs to start the subscription flow again — or you can manually confirm them via the Admin API if needed. Extending the token expiry prevents the issue from happening in the first place.
Can I disable the double opt-in confirmation email in Ghost?
No. Ghost's double opt-in is not configurable — it's baked into the membership flow and can't be turned off through the admin panel or config files as of 2026. It exists for GDPR compliance and list quality.
What if the confirmation link gives an error instead of a 404?
An error (500 or similar) on the members API endpoint typically points to a Ghost process crash or a database issue. Check ghost log and look for errors around the time of the failed click. Out-of-memory crashes are a common culprit on low-spec servers.
Does this affect Ghost Pro hosted sites the same way?
Ghost Pro sites can still hit the welcome page 404 and URL-related issues. The token expiry fix isn't available on Ghost Pro (no core file access). If expiry is your issue on Ghost Pro, contact Ghost support directly.
How do I find out which cause is affecting my site?
Use the diagnostic table above and test in this order: check your Ghost logs, verify the welcome page setting in Tiers, confirm your config.production.json URL matches your live domain, then temporarily disable Cloudflare proxy to isolate network-level issues.
Will updating Ghost fix the confirmation 404?
Unlikely, unless it's a known bug fixed in a specific version. Ghost updates sometimes reset the magic-link expiry back to 10 minutes if you've edited that file. Always check after updating. See our guide on how to update Ghost safely.
The fastest path to fixing this: extend the magic-link expiry to 1 day, clear your welcome page setting (or verify it points to a real page), and confirm your Ghost URL config matches your live domain. That covers 90% of cases. If subscribers still hit a 404 after those three changes, pull your Ghost logs and look for the specific path that's failing — the fix becomes obvious once you see the actual error.