GhostArch Hosting for Ghost authors
Log in Get Started

How to move a Ghost blog to a new host without downtime

Moving a Ghost blog is usually painless. The outages happen for predictable reasons: DNS changed before the destination was ready, or the database moved hours before the images did, and readers spent the gap looking at a broken site.

Here is the ordering that avoids it.

What actually has to move

A Ghost site is three things:

  1. The database — posts, pages, members, users, settings.
  2. The content/ directory — images, uploads, themes.
  3. The domain — the DNS record pointing at a server.

Move 1 and 2 first. Move 3 last, and only once the destination is serving correctly.

Step 1 — Lower your DNS TTL, days early

This is the step people skip, and it is the one that decides how long your cutover window is.

Your DNS record has a TTL telling resolvers how long to cache it. If it is 24 hours, some readers keep hitting your old server for a day after you change it.

Set the TTL to 300 seconds at least 48 hours before you migrate. You are not changing where the record points, only how long it may be cached. By migration day, the whole internet is holding a five-minute copy and your cutover window collapses from a day to minutes.

Put the TTL back up afterwards.

Step 2 — Export everything

From Ghost admin: Settings → Labs → Export your content for a JSON of posts and settings.

That export does not include your images. Take content/ separately:

tar czf ghost-content.tar.gz -C /var/www/ghost content

If you have shell access, a database dump is better than the JSON export — it carries members and internal state the JSON does not:

mysqldump --single-transaction -u ghost -p ghost_prod > ghost.sql

Step 3 — Build the destination and rehearse

Set the new site up completely, still on the old host's DNS. Restore the database and content/, and get Ghost running.

Test it before touching DNS. You do not need the domain to do this — send the Host header yourself:

curl -H "Host: yourblog.com" http://NEW.SERVER.IP/ | head -40

If that returns your homepage, the destination works. You have now removed the only real risk from the cutover.

Check specifically:

  • The homepage and a couple of posts render.
  • Images load — this is where a forgotten content/ shows up.
  • /ghost/ reaches the admin panel.
  • The post count matches the old site.

Step 4 — Final sync, then cut over

Your rehearsal data is now slightly stale. Re-sync the database and any new uploads immediately before switching:

mysqldump --single-transaction -u ghost -p ghost_prod > final.sql
rsync -az /var/www/ghost/content/ new-server:/var/www/ghost/content/

Then change the DNS A record. With a 300-second TTL, traffic moves over in about five minutes.

Step 5 — Certificates

If the new host issues Let's Encrypt certificates automatically, this happens on its own once DNS resolves — HTTP-01 validation needs the domain pointing at the new server, so the certificate cannot be issued before the cutover.

That is normal, and it is why you keep port 80 open and serving /.well-known/acme-challenge/ during the switch. A host that redirects everything to HTTPS before it has a certificate has created a chicken-and-egg problem for itself.

Step 6 — Keep the old server for a week

Do not delete it. Keep it running, untouched, for a week.

If something is wrong, reverting is a DNS change back — and readers on stale DNS keep landing on a working site rather than a dead IP. It costs a few dollars and it is the cheapest insurance in this process.

The ordering that causes the outage

For completeness, this is the sequence to avoid:

  1. Change DNS first.
  2. Then start setting up the new server.

Readers arrive at a half-built site. Under a long TTL, some of them keep arriving for a day. Every migration horror story is some version of this.

Destination ready → verified by Host header → final sync → DNS → certificate. In that order, nobody notices.


If you are moving to us, the how it works page covers what happens after you point the record, and you can bring your own domain on any plan.

Ready to start writing?

Your blog, your domain, your database — running in about a minute.