GhostArch Hosting for Ghost authors
Log in Get Started

What Ghost actually needs to run: a hosting requirements checklist

Most "Ghost hosting requirements" pages copy the docs and stop. This one is written from provisioning Ghost repeatedly on fresh containers, and includes the parts that only show up when an install fails at 2am.

The short version

Requirement What Ghost needs Common mistake
Node.js An even-numbered LTS that Ghost explicitly supports Installing the newest Node
Database MySQL 8 Assuming MariaDB is interchangeable
Memory 1 GB minimum, 2 GB comfortable Sizing from idle usage
Process manager systemd (or Docker) Running ghost start in a shell
TLS A real certificate Leaving HTTP-only "for now"

Node: newer is not better

This is the single most common self-hosting failure, and it is counter-intuitive.

Ghost pins the Node versions it supports in its engines field, and ghost-cli refuses to install on anything outside that range — including newer LTS releases. Ghost 6 declares ^22.23.1. Node 24 is a perfectly good LTS, and ghost-cli will still reject it.

So "install the latest Node LTS, then install Ghost" produces a hard failure, and the error does not obviously say "your Node is too new".

Check before you upgrade anything:

node --version
npm view ghost engines.node

If those disagree, fix Node first. On a running site, upgrading Node underneath Ghost is worse than not upgrading — you can end up with a site that will not restart.

MySQL 8, not MariaDB

Ghost supports MySQL 8. MariaDB is a fork of MySQL, it speaks the same wire protocol, and it will appear to work — which is exactly the problem. You will not find out that it is unsupported until a migration in some future Ghost release behaves differently.

We tested MariaDB 12.3 against Ghost and it did run. We still ship MySQL 8, because "it worked when I tried it" is not the same as "upstream tests it".

SQLite is fine for local development and genuinely not fine for a production site of any size.

Memory: size for the install, not for idle

An idle Ghost process sits around 350–450 MB. That number is misleading, because the peak is not at runtime — it is during ghost install, while npm resolves and builds the dependency tree.

Give a new install under 1 GB and it does not error. It gets OOM-killed part way through, which looks exactly like a hang. You wait, nothing happens, and there is no useful message anywhere.

Provision with at least 1 GB. If you plan to run ghost update on the same box, 2 GB removes a whole class of mystery.

The 127.0.0.1 trap

By default Ghost binds to 127.0.0.1. On a single server with nginx in front, that is correct and secure.

Inside a container or VM with a reverse proxy outside it, that default makes Ghost unreachable — the proxy connects across a bridge interface and finds nothing listening. The site is running perfectly and answers nothing.

ghost config server.host 0.0.0.0

This is a real configuration step, not a nicety. If you are proxying from another host, you need it.

Backups are a database plus a folder

A complete Ghost backup is two things:

  1. A dump of the MySQL database (posts, users, members, settings).
  2. The content/ directory (images, themes, uploads).

A database dump alone restores a site whose images all 404. Copying content/ alone restores a folder of pictures and no posts.

Test the restore. An untested backup is a hypothesis.

What you are actually signing up for

Self-hosting Ghost is not hard. It is a series of small, specific decisions where the obvious choice is wrong: newest Node, "MariaDB is basically MySQL", sizing memory from idle, leaving the default bind address. Each is a twenty-minute problem the first time and a five-minute problem afterwards.

If that sounds like a reasonable afternoon, self-host — Ghost is well-built software and it will run for years. If you would rather not own it, that is what managed hosting is for: we make these choices once, on every container, and keep making them when Ghost changes them.

Ready to start writing?

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