A headless CMS manages content (articles, products, pages, media), and delivers it through an API, leaving the presentation to your frontend: a static site, a Next.js app, a mobile app, or all of them. Several excellent options are open source and run on your own VPS. Here’s how they compare.
Background: Jamstack explained.
At a glance
| CMS | Stack | APIs | Best for |
|---|---|---|---|
| Strapi | Node.js; PostgreSQL/MySQL/SQLite | REST + GraphQL | Custom content models, developer-friendly admin. See deploy Strapi |
| Directus | Node.js; wraps any SQL database | REST + GraphQL | Admin UI on top of existing databases; data apps. See deploy Directus |
| Payload | Node.js/Next.js; MongoDB or Postgres | REST + GraphQL + local API | Code-first config in TypeScript; app + CMS in one |
| Ghost | Node.js; MySQL | Content API | Blogs, newsletters, memberships. See Ghost |
| WordPress (headless) | PHP; MySQL | REST + WPGraphQL | Familiar editing, huge plugin ecosystem. See headless WordPress |
| Decap / TinaCMS (Git-based) | Content in Git (Markdown) | Git | Small sites, docs, developer-run blogs |
Key differences
Content modelling. Strapi and Payload define content types in the admin or in code. Directus introspects your SQL database, so you can put an admin panel on an existing schema. Ghost has a fixed model (posts, pages, tags, members), which is simple but less flexible.
Editing experience. Ghost and WordPress offer polished writing experiences. Strapi, Directus and Payload are better for structured data (products, events, translations) than for long-form writing, though all have rich text editors.
API style. All offer REST, and most GraphQL. Payload’s local API (direct function calls inside a Next.js app) avoids HTTP overhead.
Licensing. Strapi (MIT community edition), Payload (MIT), Ghost (MIT) and WordPress (GPL) are open source. Directus uses the BSL, which is free for organisations under a revenue threshold. Check current terms for commercial use.
Hosting requirements
| CMS | Typical small setup |
|---|---|
| Strapi / Payload / Directus | Node.js + PostgreSQL, 1–2 vCPU, 2 GB RAM |
| Ghost | Node.js + MySQL, 1–2 GB RAM |
| WordPress | PHP-FPM + MySQL, 1–2 GB RAM |
| Git-based | No server needed (only for the site build) |
All run well with Docker Compose on a VPS, with Nginx in front for HTTPS, and media in local storage or S3-compatible object storage. See Docker Compose in production and MinIO.
Connecting the frontend
- The CMS fires a webhook on publish.
- CI rebuilds the static site (or the framework revalidates the changed pages).
- The new build is deployed.
Lock down the admin UI (strong passwords, 2FA, optional IP restriction), and give the frontend a read-only API token. See API security best practices.
Which to choose
| Situation | Suggestion |
|---|---|
| Blog or publication with newsletters | Ghost |
| Custom structured content, developer team | Strapi or Payload |
| Admin UI over an existing SQL database | Directus |
| Editors already love WordPress | Headless WordPress |
| Small developer-run site | Git-based (Decap, or plain Markdown) |
Backups and updates
Back up the database and uploaded media, and update CMSs regularly (admin panels are attack targets). Test major upgrades on staging. See updating self-hosted apps and database backup automation.
Quick reference
| CMS | One-line summary |
|---|---|
| Strapi | Flexible Node.js CMS with content-type builder |
| Directus | Admin + API on any SQL database |
| Payload | TypeScript, code-first, Next.js-native |
| Ghost | Publishing + memberships |
| WordPress | Familiar, huge ecosystem |
Related: static site generators compared and deploy Next.js on a VPS.