Migrate from Substack to Ghost: what moves, who does the work and how hard it is
Ghost's Substack migrator moves posts and members into a self-hosted Ghost site, so your archive and subscriber list can come with you. Paid subscriptions need a separate, deliberate step: the Stripe account that bills your members must be reconnected to Ghost, or paying members will not keep paying through the new site. Ghost takes no transaction fee on paid subscriptions, but Stripe processing fees still apply after the move, so card costs stay with you. Before you rely on the migrator, confirm with Ghost's current migration documentation exactly which member states, paid tiers, comped accounts and post formats it carries across, and check that list against your own publication.
The move is usually run by the publisher together with either an implementation partner or an in-house platform engineer. The publisher owns the decisions about tiers, pricing, branding and which content is worth keeping, while the engineer installs and secures Ghost. Ghost's Ubuntu install guide lists supported Ubuntu releases, a supported Node.js version, MySQL 8.0 or 8.4, NGINX 1.9.5 or later, systemd and at least 1 GB of RAM, with installation through Ghost-CLI. That guide also notes that Ghost-CLI installs do not support web analytics, so plan analytics as a separate workstream. Effort depends mainly on archive size, the number of paid tiers, domain and redirect work, and any Substack features your readers rely on. Ask any provider for a written scope that separates what migrates automatically from what is rebuilt by hand and who verifies each paid member's billing after the switch.
The migration stays reversible until you change DNS or billing. Keep the custom domain pointed at Substack while the Ghost site is built, imported and tested on a staging address, and confirm that test members can sign in and that paid access works. Old Substack post addresses should be mapped to their Ghost equivalents, and the redirect rules tested before the domain moves, because link equity and search traffic depend on them. Do not cancel the Substack subscriptions or change the Stripe connection until the test results are signed off. Larger archives may call for Ghost's own migration tooling or services, so confirm with Ghost whether those options apply to a Substack export before you commit a launch date.
Which Substack features map to Ghost and which need rework
This table compares Substack's core publishing, subscription and discovery features with what Ghost provides out of the box, and marks each as clean, needs rework or gap. Read the status column first, then confirm the rows your readers depend on before you set a cutover date. The main takeaway is that publishing, paid memberships and email map well to Ghost, while Substack's discovery network does not carry over.
| Substack feature | Ghost equivalent | Status and what to do |
|---|---|---|
| Publishing posts and archive | Built-in post editor and public archive | Clean. Posts import through the migrator, but confirm embeds, images and custom formatting after import. |
| Free and paid subscriptions | Built-in memberships and paid subscriptions | Needs rework. Ghost has no transaction fee, but Stripe fees still apply. Reconnect the same Stripe account so existing paid subscribers keep paying. |
| Member lists and subscriber data | Members in Ghost Admin with import and export | Needs rework. Export members and check that subscription status, tiers and billing dates carry over before you switch. |
| Custom domain and branding | Own domain with custom themes | Needs rework. Plan DNS, SSL and redirects from Substack URLs to Ghost URLs so links and search visibility survive. |
| Email newsletter delivery | Built-in newsletters sent through your configured email service | Needs rework. Set up a bulk email provider and verify sender domain authentication before sending to members. |
| Recommendations and discovery network | No equivalent network | Gap. Ghost does not replicate Substack's recommendation or discovery features. Confirm which referral traffic you rely on and plan replacement through your own marketing channels. |
| Comments and community notes | Built-in comments with member controls | Needs rework. Confirm moderation settings and whether historical comments migrate. Substack Notes has no direct Ghost equivalent. |
| Web design and themes | Ghost themes and visual editor settings | Needs rework. Substack layouts do not transfer. Choose or build a Ghost theme and retest templates on mobile. |
Which posts, members, Stripe links and domains move, and what to rebuild
Four things carry a Substack publication into Ghost: the archive, the member list, the paid subscriptions and the domain. Each moves by a different path, and each needs a check before you cut over.
Posts and the archive
Start by requesting your full export from Substack, then run Ghost's Substack migrator against that file to bring posts into Ghost. Confirm the exact export file format and what the migrator carries across, including images, post dates, tags and drafts, against the current Ghost and Substack documentation at the time you work. Ghost's documented WordPress import limits (2,500 posts, XML files up to 100 MB) describe the WordPress path only, so do not apply them to a Substack export. Check the imported archive post by post for broken embeds and formatting before you retire the old one.
Free and paid member records
Members come across as contact records, and the migrator is the path to confirm for both free and paid subscribers. Ask which member fields (email address, sign-up date, subscription status, complimentary or gifted access) carry over and which must be re-created by hand. Keep a copy of the Substack subscriber export as your fallback and reconcile counts on both sides before you send any announcement, because a mismatch here becomes a support problem for readers.
Stripe subscriptions and the connected account
Paid subscribers keep paying only if the Stripe account that holds their subscriptions is the one Ghost is connected to. Plan the Stripe side with your finance team first, decide whether to reconnect the same account or move subscriptions, and confirm with Ghost's current membership documentation how existing subscriptions are handled. Stripe processing fees still apply in Ghost, and Ghost takes no transaction fee on paid subscriptions. Test one paid checkout and one renewal path in a staging setup before any reader is affected.
Custom domain and redirects
Point your domain at the Ghost server and terminate TLS there, using the NGINX setup described in Ghost's install guide as your baseline. Old Substack URLs (the publication address and individual post links) need permanent redirects to the matching Ghost addresses, so search rankings and shared links keep working. Map every old URL pattern before cutover, keep the Substack publication live with a notice during the transition, and confirm redirect behavior with the documentation for your Ghost version.
Content API and integrations to rebuild
Ghost's Content API is read-only and returns JSON, so it suits reading published posts into another site or app, not writing subscribers or payments back. Any Substack-side automation, custom embeds or third-party tools must be rebuilt against Ghost's own integrations, with keys created through a Custom Integration in Ghost Admin. Inventory every tool connected to the Substack publication and assign each one a replacement or a retirement decision before cutover.
The migration sequence from export to decommission
The sequence moves your publication from Substack to a self-hosted Ghost site in five gated steps, so members, paid subscriptions and links carry over before Substack is switched off. Each step ends with a written output that the next step depends on.
Inventory subscribers, payments and dependencies
Before any export, the publisher and whoever owns the Stripe account list what the publication depends on: free and paid subscriber counts, which Stripe account collects payments, the domain and DNS host, embedded content such as podcasts, polls and third-party forms, and any tools that read the Substack feed or send to it. Confirm with Substack how its export covers paid members and what it does not include, and confirm with Stripe who holds the account and its API access. The output is a written inventory with one owner per item and a list of links that must keep working, which becomes the input for the redirect map later.
Prepare the Ghost install and pilot the import
Provision a server that meets Ghost's Ubuntu install guide: Ubuntu 22.04, 24.04 or 26.04, a supported Node.js version (the guide's example uses Node 22), MySQL 8.0 or 8.4, NGINX 1.9.5 or later, systemd and at least 1 GB of RAM. Install Ghost through Ghost-CLI, then create the Substack export and load it into a staging Ghost instance that is not public. Staging is where the team learns which posts, images and member records arrive cleanly and which need manual repair. The output is a member reconciliation report that compares the export's counts and tiers with what Ghost shows, plus a list of posts that need manual fixes.
Run the parallel environment on a subdomain
Run the production-like Ghost site on a subdomain, such as a staging address, while Substack stays live for members. Connect Stripe in test mode, then test member sign-up, magic-link login, a free-to-paid upgrade, a paid renewal and a cancellation using Stripe's test cards, and confirm that newsletter emails send from the correct sending domain. Check that the RSS feed, archive and tags render as expected. The output is a signed-off test checklist with a named owner for each row, and any failing rows are fixed and retested before cutover is scheduled.
Cut over members, payments and DNS
Take a final Substack export, import it into the production Ghost site, and reconcile member counts against the inventory from step one. Reconnect the same Stripe account that already collects subscription payments so paid subscribers keep their billing relationship, and confirm that the existing subscription records and prices are mapped correctly before any live charge runs. Update DNS to point the publication's domain at Ghost, then send a notice to members explaining the change, the login step and what to do if a charge looks wrong. The output is a cutover log showing the final export time, reconciliation results, the DNS change record and the notice sent.
Verify redirects and decommission Substack
Keep Substack in read-only mode for a period the publisher sets in advance, so old links and member questions still resolve while the new site settles. Verify that every URL in the redirect map returns the intended Ghost page, that canonical tags and feeds point to the new domain, and that paid members can still log in and see gated posts. Only after those checks pass, retire the old DNS records and any leftover subdomain records, and cancel the Substack publication. The output is a redirect verification report and a decommission record that names who approved the shutdown and when DNS was changed.
What drives migration cost and duration, and how to keep each down
This table lists the factors that change how much work a Substack to Ghost move takes and what it costs to run afterward. Read each row as a question to answer before you request a fixed-scope quote, because most drivers can be reduced by decisions made early.
| Driver | Why it matters | How to contain it |
|---|---|---|
| Archive size and media volume | Post count, image and video volume and embedded files set the import time, storage footprint and the amount of checking after import. Ghost's WordPress docs show that import limits exist, but the Substack export follows its own path, so confirm limits for your archive. | Export a full archive early, count posts and media, remove dead or duplicate drafts, and ask the partner to test a sample import before committing to the full run. |
| Number of paid tiers and active paid members | Each paid tier needs a matching Ghost tier and price, and each active paid member must be mapped correctly. Errors here affect revenue directly, so this work grows with tier count and member count. | Reduce tiers before migrating, document one-to-one tier mapping in writing, and ask for a reconciliation step that compares member counts and statuses before and after cutover. |
| Custom integrations, embeds and widgets | Substack embeds, third-party forms, comment tools, recommendation widgets and custom scripts do not carry over automatically. Each one needs a replacement or a deliberate decision to drop it. | Inventory every embed and script on the site and in posts, mark each as keep, replace or retire, and agree the replacement list in the written scope. |
| Custom domain and redirect complexity | Old Substack URLs, custom domain settings, sitemaps and feed subscribers depend on correct redirects. Mistakes lose search traffic and break links shared in newsletters and social posts. | Build a URL map from the export, decide on the canonical domain, plan redirects before DNS changes, and test a sample of old links after go-live. |
| Stripe account state and open disputes | Paid subscriptions depend on the same Stripe account staying in good standing. Open disputes, restricted accounts, or unclear account ownership can delay reconnection and interrupt billing. | Review Stripe account status, resolve or document open disputes, confirm who holds administrative access, and schedule the reconnection with the account owner present. |
| Staffing mix: in-house or partner | In-house staff carry the knowledge of the publication but may lack Ghost server and billing experience. A partner adds cost but shortens the time that the publication runs without a clear owner. | Ask for a fixed-scope written quote that names who does each task, what the client must provide, and what is excluded, then compare it with the internal hours you would commit. |
| One-time work: migration, redirects and testing | Import, tier setup, redirect mapping, template work and cutover testing happen once but must be finished before the publication moves. Rework here is the most common source of overrun. | Set acceptance criteria for each one-time task, such as a checked redirect list and a verified test payment, and tie payment milestones to those criteria. |
| Recurring work: server operations and upgrades | A self-hosted Ghost install needs patching, Node.js and database maintenance, and regular Ghost upgrades. Ghost ships frequent releases, so this work recurs for the life of the site. | Confirm the supported stack in the Ghost install guide, decide who applies upgrades, and ask whether ongoing support is a separate retainer in the quote. |
| Recurring work: email deliverability and backups | Sending newsletters from your own domain requires sender authentication, bounce handling and monitoring. Backups of the database, media and configuration must be restorable, and this effort continues after launch. | Verify your email provider and sending domain before cutover, assign someone to watch bounce and complaint rates, and ask for a tested restore procedure as a deliverable. |
Keeping paid subscribers paying through the Stripe reconnection
The Stripe account is the highest-risk part of moving a paid publication from Substack to Ghost, because it holds the recurring charges your paid members already rely on. Ghost's comparison page says Ghost takes no transaction fee on paid subscriptions, but Stripe processing fees still apply, so the same Stripe account will keep handling card payments after the move. Your job is to make sure every existing subscription continues without a gap, a duplicate charge or a silent cancellation. Before you touch production, confirm with Stripe's documentation and Ghost's membership documentation exactly how subscription records are linked to Ghost members, because that linkage determines whether an existing subscription is recognized or whether members must be asked to subscribe again.
Start in Stripe test mode. Connect a Ghost staging instance to a test environment, import a representative set of members, including free, monthly and annual paid members, and confirm that each one maps to the right tier and billing interval. Then run a full cycle: a new subscription, a plan change, a cancellation and a failed payment using Stripe's test cards. Record what Ghost shows for each case. Before cutover, export your Substack member list and your Stripe subscription list, and reconcile counts by plan tier and status (active, past due, canceled, free). Keep the reconciled numbers in a signed-off sheet, and repeat the same reconciliation after cutover. Any mismatch should be resolved before you send announcements, not after.
Decide in advance how failed payments and cancellations are handled during the switch. Stripe's dunning settings govern retries for past-due invoices, so review them with your billing owner and avoid changing retry behavior in the middle of the migration. Members whose payments are past due should not be silently moved to a free tier, and members who cancelled on Substack should not be reactivated without their consent. Ask Ghost's team or your implementation partner to document which Stripe objects Ghost reads and writes, and who in your organization can approve a change to a live subscription. Plan a short window where you monitor new charges and support requests daily, with a named person responsible for answering member billing questions.
What usually goes wrong and how to prevent it
Most failed Substack to Ghost moves do not fail in the import itself. They fail in the parts around it: member access, billing, URLs, email authentication, traffic and server operations. Each card below names one failure and the control that prevents it.
Members lose access or get duplicate emails
Importing members and then sending a welcome or re-subscribe campaign can email people twice or lock out readers who expected to keep their login. Before the first send, compare the member count in the Substack export with the count in Ghost Admin, and confirm which list receives the launch announcement. Send one controlled message to an internal test list first, then to the full audience.
Paid subscriptions stop renewing
Paid members are tied to a Stripe account and its subscription objects, so a new Stripe account or a missed reconnection can leave subscribers without an active plan at renewal. Reconnect the same Stripe account in Ghost, then check that a sample of paid members shows an active subscription and the expected next billing date. Ask your Stripe administrator to confirm the webhook endpoint points to your new Ghost domain.
Broken links and lost search rankings
Substack post URLs follow a different structure from Ghost, so inbound links and search results can return errors after cutover. Build a redirect map from every old Substack URL to its new Ghost address, and load-test a sample of high-traffic posts before DNS changes go live. Keep the map in version control so later edits do not silently remove a redirect.
Deliverability drops on the new sending domain
Mail sent from a new domain without matching SPF, DKIM and DMARC records often lands in spam, and the damage shows up in engagement numbers before anyone notices. Publish the sending records for your Ghost mail provider and confirm DKIM signing and a DMARC policy with a DNS lookup tool before the first newsletter. Warm the domain gradually with your most engaged readers rather than sending the full list on day one.
Losing discovery traffic from Substack
Substack surfaces newsletters through its own recommendations and network, and a self-hosted Ghost site receives none of that traffic automatically. Plan the audience move as a deliberate campaign: announce the new address to existing readers, add a clear subscribe path on every post, and track referral sources in the first months. Treat the drop as a known cost in your business case rather than a surprise.
An unowned server with no upgrade plan
A self-hosted Ghost install needs patches, database backups and a named owner, or it becomes a security exposure after the migration team leaves. Assign an owner, schedule regular database and content backups, and test a restore on a separate server. Confirm the supported Ubuntu, Node.js and MySQL versions in the install guide before each upgrade, and track Ghost releases so updates are applied on a set schedule.
How the migration changes by publication size and starting point
A publication with a free list and no paid tier has the shortest path. There are no payment relationships to carry over, so the work centres on the subscriber list, the posts and the sending setup. Ghost's memberships are built in, so you can keep the free tier only and turn on paid subscriptions later without changing platforms.
- Subscriber consent: Confirm that the export contains only addresses that opted in, and that your new sending provider accepts them under your existing consent records.
- Sending setup: Configure email delivery and sender authentication for your domain before the first send from Ghost, so the first newsletter does not arrive from an unverified sender.
- Archive size: A short back catalogue moves quickly through Ghost's Substack migrator, and most of the time goes to checking formatting on a handful of posts.
- Subscription forms: Replace Substack's embedded signup widgets on your site with Ghost's signup links and check that old subscribe URLs redirect.
Confirm with your team which addresses are safe to import and who signs off the sending domain before you schedule the cutover.
A paid publication has active subscriptions that people expect to keep billing without interruption. The main risk is not the posts but the payment relationship, so the sequence has to protect paid members first. The Stripe account you use with Ghost is the key decision, because reconnecting the same account is what lets existing subscriptions continue.
- Stripe account ownership: Check who holds the Stripe account and its administrator roles, since reconnecting to Ghost needs access to the same account.
- Member and plan mapping: Confirm that each paid tier and price in Ghost matches what subscribers currently pay, including annual and discounted plans.
- Billing communication: Plan a message to paid members explaining any change in the sign-in or billing portal before the switch, so they do not treat it as a new charge.
- Parallel period: Keep Substack live until you have verified imported paid members and a test subscription path in Ghost.
- Fees: Ghost takes no transaction fee on paid subscriptions, but Stripe processing fees still apply, so your net figures will change even though the price does not.
Confirm with your payment provider and Stripe administrator exactly how existing subscriptions will continue, and get a written plan for handling failed payments during the switch.
A publication with many years of posts, heavy embedded media or custom layouts needs more planning before the first import. Ghost's migration documentation says custom post types, most uncommon shortcodes and content-restriction plugins do not migrate, and it points larger migrations to the open-source TryGhost/migrate toolkit or to Ghost(Pro)'s migrations team. Substack's export format and embedded content will also need checking.
- Content inventory: List posts with embeds, images, audio, video and any Substack-specific blocks, then sample them to see what survives the import.
- Media location: Decide whether images stay on Substack's CDN or move to your own storage, because links to hosted media can break once the old account closes.
- Batch testing: Run the import on a copy of the export and review a representative set of posts before importing the full archive.
- Link integrity: Build a list of internal links and canonical URLs that must redirect, and check them after each test run.
- Toolkit choice: Compare the open-source toolkit with a managed migration on the basis of your post count, media volume and the time you can spare for review.
Confirm with the Ghost project which migration path fits your archive, and ask for a written list of content that will not migrate so you can plan manual rework.
A publication that already runs its own domain on another CMS usually has the most existing URLs, templates and integrations to reconcile. The question is less about moving the newsletter and more about how Ghost fits beside or in place of the current site. Ghost's Content API can deliver content to other sites or apps, which may matter if parts of the current site stay on another system.
- URL structure: Map current paths to Ghost routes and decide where redirects are needed, so search traffic and bookmarks keep working.
- Hosting split: Decide whether Ghost replaces the whole site or runs alongside other pages, and whether the Content API serves the rest.
- Ghost hosting: Ghost's Ubuntu install guide uses Ghost-CLI, which does not support web analytics, so a Docker Compose install may be needed if analytics or ActivityPub matter to you.
- Existing integrations: Inventory forms, tracking tags, comment systems and marketing tools, and decide which move to Ghost and which stay.
- Cutover window: Plan DNS and redirect changes together so readers do not hit two versions of the site.
Confirm your URL map, your analytics requirements and the Ghost installation method with your technical owner before any DNS change.
How much effort, time and input does a Substack to Ghost move need?
How long does a Substack to Ghost migration take?
The duration depends mainly on the size of the archive, the number of paid tiers and integrations, and how much custom work the publication has. A plain newsletter with a few hundred posts and a free list moves faster than a paid publication with several tiers, custom domain redirects and third-party embeds. Ghost's migrator handles posts and members, but everything around it, including Stripe reconnection, testing and DNS cutover, takes deliberate time. Ask any provider for a written timeline that lists each step, its owner and the test results required before cutover, since no fixed duration can be assumed from this page.
Can a publisher run the Substack to Ghost move alone?
A technically confident publisher can move a simple publication alone, provided they can export from Substack, run the Ghost migrator, and install and operate Ghost on a server. Paid publications are harder because Stripe, DNS, email authentication and member access all need to line up at cutover. Ghost's documentation notes that custom post types, most uncommon shortcodes and content-restriction plugins do not migrate, and that larger migrations may need the open-source TryGhost/migrate toolkit or Ghost(Pro)'s migrations team. Decide early which parts you will own and which you will hand to a specialist.
What access and input does the publisher need to provide?
The work needs several inputs before it starts:
- Administrator access to the Stripe account that holds the current paid subscriptions, so the same account can be reconnected to Ghost.
- Control of the domain's DNS records and the custom domain, including the ability to set up redirects from old Substack URLs.
- A written list of paid tiers, prices, free tiers and every integration, embed and tracking tool in use.
- Sign-off on test results, covering sample posts, member login, paid access and email delivery, before the old site is switched off.
Ask for these inputs in the written scope so that no step waits on access that was never requested.
Do paid subscribers keep paying after the move?
Paid subscribers keep paying when the same Stripe account is reconnected to Ghost and the subscription products are recreated correctly. Subscribers should not need to re-enter card details if the payment relationship stays in that account, but this must be tested with real test subscriptions before cutover. Ghost takes no transaction fee on paid subscriptions, though Stripe processing fees still apply. Confirm with the provider how existing subscriptions, billing dates and any subscriber who lapsed during the move will be handled, and ask for that in writing.
What happens to the Substack archive after cutover?
After cutover, the posts move into Ghost, and the Substack archive is no longer the publication's home. Old Substack links should redirect to the matching Ghost URLs so that search engines, shared links and subscriber bookmarks keep working. Keep a full copy of the Substack export as an offline archive, and keep the export files in storage you control. Check after launch that redirects resolve for your highest-traffic posts, and confirm with the provider which redirect rules they will configure and test.
What ongoing work does a self-hosted Ghost site need?
Self-hosting moves recurring work to your team or a support provider. Ghost ships frequent minor releases, so someone must apply updates, test them and keep the server, Node.js, MySQL and NGINX supported. You also need backups of the database and content, monitoring, email deliverability checks, and TLS certificate renewal. Ghost-CLI installs do not support web analytics, so analytics needs a separate Docker Compose install if you want it. Ask any provider whether they offer ongoing upgrades, backups and monitoring as a retainer, and what those cover in writing.
What should a quote for this move include?
A useful quote lists each component as its own line: discovery, environment setup, migration of posts and members, Stripe reconnection, custom domain and redirect work, testing with sign-off, cutover, and handover documentation. It should also state what is out of scope, such as custom post types or unsupported plugins, and what happens if testing finds problems. Separate one-time work from recurring retainers for upgrades and backups. DeployOpen works from a written scope with agreed deliverables and timelines before work starts, and provides quotes that follow from that scope.
How DeployOpen scopes, runs and supports a Substack to Ghost migration
DeployOpen is a Chainscore Labs company that plans, implements, customizes, integrates, hardens, backs up, upgrades, documents and supports self-hosted open-source platforms inside the client's own infrastructure. For a Substack to Ghost move, we work from a written scope that covers the publication's content, members, paid subscriptions and domain, and the work runs inside your own cloud account or data center.
How we scope
- Inventory posts, pages, tags, members, paid subscriptions and the Stripe account before any work starts
- Agree in writing which content, redirects and domain changes are in and which are out
- Confirm the target Ghost hosting environment, database and email delivery provider with your team
- Most engagements are fixed-scope, with deliverables and timelines agreed in writing before work begins
How we build
- Install and configure self-hosted Ghost in your environment using the documented Ghost-CLI or Docker Compose path
- Run the Substack export and Ghost's migrator in a staging instance, then review posts, members and tags
- Test paid subscriber reconnection to the same Stripe account and confirm renewals before cutover
- Set up custom domain, NGINX configuration and redirect rules, then test them against the old Substack URLs
How we hand over
- Document the installation, configuration, migration steps, redirect map and rollback procedure
- Hand over admin access, backup and restore runbooks, and a list of items that did not migrate and need manual handling
- Walk your editorial and operations staff through publishing, member management and Stripe reporting in Ghost
- Provide written records of what was tested and what remains open at handover
How we support
- Ongoing support, Ghost upgrades and continuous testing are available as retainers after handover
- Retainers can cover version upgrades as Ghost releases new versions, with testing before each rollout
- Keep backups of content, members and configuration under the runbook agreed in the scope
- Confirm response expectations and maintenance windows with us in writing before the retainer starts

