Deploy Strapi — Self-Hosted Headless CMS, Contentful Alternative
Self-host Strapi 5: headless CMS with REST & GraphQL. No $300/mo Contentful
Just deployed
/var/lib/postgresql/data
Just deployed
/public/uploads
Deploy and Host Strapi on Railway

Strapi is the most popular open-source headless CMS — 72k+ GitHub stars and the largest headless community — built on Node.js with a visual content-type builder that auto-generates REST and GraphQL APIs from your schema. Strapi 5 adds the Document Service API, content history and versioning, draft/publish workflows, a Vite-powered admin, and TypeScript-first projects. Model content in the browser, consume it from any frontend (Next.js, Astro, Vue, mobile), and own the whole stack. This template deploys Strapi 5 with PostgreSQL and a persistent volume.
Contentful's Team plan costs $300/month. Strapi self-hosted is free (MIT) — you pay only compute, ~$10–20/month on Railway. No per-seat fees, no API-call metering, no vendor lock-in; your content lives in your own PostgreSQL database.
What This Template Deploys
| Service | Purpose |
|---|---|
| Strapi 5 | The headless CMS — content-type builder, admin panel, auto-generated REST + GraphQL APIs, on the public web service |
| PostgreSQL 16 | Production database — content, users, roles, and API tokens. Strapi requires SQL; Postgres is the production standard |
| Persistent Volume | Mounted at /opt/app/public/uploads — media library files survive redeploys (or use S3/Cloudinary for scale) |
All services connect over Railway's private network with credentials injected automatically. Using PostgreSQL (not SQLite) is deliberate and required: a SQLite file on an ephemeral container would lose all content on redeploy. This template wires Postgres correctly from the start.
About Hosting Strapi
Strapi is a Node.js app backed by a SQL database with a media library on disk. Production means a persistent server, PostgreSQL, media storage that survives restarts, and a public HTTPS endpoint. This template wires the app, Postgres, and a media volume on Railway automatically.
Two production requirements, both handled here: use PostgreSQL, not SQLite (SQLite is dev-only and non-persistent on cloud platforms), and persist media — Strapi's local file storage doesn't survive redeploys without a volume, so this template mounts one (use S3/Cloudinary for scale).
Security — keep it patched: Strapi disclosed serious vulnerabilities in May 2026 (unauthenticated admin access and SQL injection), patched in v5.33.2. Deploy a current patched version and keep it updated — self-hosted teams that delay updates carry real risk. Pin to a known-good tag rather than an unpinned
latest.
Typical cost: ~$10–20/month on Railway for Strapi and PostgreSQL. Contentful's Team plan is $300/month; Strapi Cloud is $18–450/month. Self-hosted Strapi on Railway is flat compute with no license fee and no per-seat pricing.
Deploy in Under 5 Minutes
- Click Deploy on Railway — Strapi and PostgreSQL build automatically (~4–5 minutes)
- Database credentials and app secrets (
APP_KEYS,JWT_SECRET) are auto-generated and wired - Add a persistent volume at
/opt/app/public/uploadsso media survives redeploys - Open
[your-domain]/adminand create your first admin account (do this promptly to claim it) - Build content types in the Content-Type Builder — your REST and GraphQL APIs generate instantly
No manual database setup. No Node server configuration. No SSL wrangling.
Common Use Cases
- Self-hosted alternative to Contentful — replace the $300/month Team plan with flat compute; no API-call metering, no per-seat fees, and your content in your own database
- Headless CMS for Next.js, Astro, or Vue — model content once, consume it via auto-generated REST or GraphQL from any modern frontend framework
- Backend for a mobile app — serve structured content and media to iOS/Android from one CMS with role-based API tokens and permissions
- Multi-channel content hub — deliver the same structured content to web, app, kiosk, and digital signage from a single API-first source of truth
- Blog or marketing site CMS — give editors a clean admin panel with draft/publish, content history, and SEO fields via community plugins, without touching code
- Developer-owned content layer — version content schemas in code and keep full control over data and infrastructure
Configuration
| Variable | Required | Description |
|---|---|---|
DATABASE_CLIENT | ✅ Pre-set | postgres — the production database client |
DATABASE_URL | ✅ Auto-injected | PostgreSQL connection string via Railway reference variable |
APP_KEYS | ✅ Auto-generated | Comma-separated app secrets for session signing |
API_TOKEN_SALT | ✅ Auto-generated | Salt for API token generation |
ADMIN_JWT_SECRET | ✅ Auto-generated | Secret for admin panel JWTs |
JWT_SECRET | ✅ Auto-generated | Secret for content API JWTs |
NODE_ENV | ✅ Pre-set | production |
HOST | Pre-set | 0.0.0.0 — bind address |
PORT | Auto-set | Railway injects the port; Strapi defaults to 1337 |
All four secrets (
APP_KEYS,API_TOKEN_SALT,ADMIN_JWT_SECRET,JWT_SECRET) must be stable across redeploys — this template generates them once via reference variables. For media at scale, configure an S3 or Cloudinary upload provider instead of the local volume.
Strapi vs. Headless CMS Alternatives
| Strapi (Railway) | Contentful | Sanity | Directus | |
|---|---|---|---|---|
| Monthly cost | ~$10–20 flat | $300/mo (Team) | Usage-based | Self-hosted |
| Self-hosted / own data | ✅ Yes | ❌ SaaS | ❌ SaaS | ✅ Yes |
| Visual content-type builder | ✅ Yes | ✅ Yes | ⚠️ Code (GROQ) | ✅ Yes |
| REST + GraphQL auto-generated | ✅ Both | ✅ Both | ⚠️ GROQ/GraphQL | ✅ Both |
| Plugin ecosystem | ✅ Largest | ⚠️ Apps | ⚠️ Growing | ⚠️ Smaller |
| Works with existing DB | ❌ Owns schema | ❌ No | ❌ No | ✅ Yes |
| Per-seat / API metering | ✅ None | ❌ Both | ❌ Usage | ✅ None |
| Open source | ✅ MIT | ❌ No | ❌ No |