Railway

Deploy Strapi

Content management system with an editor and an API for any site

Deploy Strapi

/var/lib/postgresql/data

Just deployed

strapi-media

Bucket

Just deployed

Strapi logo

Deploy and Host Strapi on Railway

Strapi is an open-source headless CMS built on Node.js. You model content as structured types — articles, products, landing pages — and Strapi gives editors a polished admin panel plus an automatically generated REST and GraphQL API to read them from any front end. Teams reach for it when a traditional CMS forces its templating on them but a bare database is too little. It powers Next.js marketing sites, mobile back ends, e-commerce catalogues and documentation portals.

Self-host Strapi on Railway and the template wires the pieces together. The strapi service builds from the gridalpha/strapi-railway repository, whose Dockerfile compiles the admin panel at build time, so containers start in seconds. A managed Postgres service stores content, users and permissions, and a Railway object storage bucket holds media uploads, so the container keeps no durable state. Postgres and the bucket stay private.

Diagram of the Strapi and Postgres services on Railway

Getting Started with Strapi on Railway

Once the deploy goes green, open the public URL and add /admin. Strapi ships no default credentials — the first visit shows a registration form creating the super administrator, and it stays open until somebody claims it, so register immediately after deploying. The password needs at least eight characters with an uppercase letter, a lowercase letter and a number.

You land on the dashboard. Click Content Manager and you will find an example Article type with title, slug, excerpt, rich-text body and cover image. Create an entry, press the refresh icon beside the slug to generate one, then hit Publish. Open Media Library and upload an image — if the thumbnail renders, your bucket and credentials are correct, because it is served straight from object storage.

To confirm the API, go to Settings → Users & Permissions → Roles → Public, tick find and findOne for Article and save. Fetching /api/articles?populate=cover now returns the entry as JSON with its cover — one request proving database, API and storage are all wired.

Strapi Media Library showing an image stored on object storage Strapi Content Manager listing a published Article entry Strapi editor with a published article's title, excerpt and body

About Hosting Strapi

Strapi separates content management from delivery. Editors work in the admin panel; your front end consumes JSON. Nothing about presentation is baked in, so the same content can drive a website, an iOS app and a digital sign at once. Self-hosting keeps the database, the media and the API in infrastructure you control, with no per-seat pricing.

Key capabilities:

  • Content-Type Builder — collection and single types with relations, components and dynamic zones
  • Auto-generated REST and GraphQL APIs with filtering, sorting, pagination and deep population
  • Draft and publish plus internationalisation for multi-locale content
  • Role-based access control for admins and API consumers, with scoped tokens
  • Media library with responsive image variants on upload
  • Plugin system and lifecycle hooks for custom logic

The strapi container runs the admin panel and API. Postgres is the system of record — every entry, user, role and API token lives there, which is why the template provisions it instead of SQLite on ephemeral disk. The object storage bucket holds uploads, so a redeploy replaces the container without losing an image.

Why Deploy Strapi on Railway

  • Postgres provisioned and connected by reference — no connection strings to copy
  • Object storage attached, so uploads survive every redeploy
  • Builds straight from the source repository on every push
  • TLS, public domain and private networking configured automatically
  • Health checks and restart policies already set

Common Use Cases

  • Marketing sites and blogs — editors publish in Strapi while Next.js, Nuxt or Astro renders statically
  • Mobile and web app back ends — one content API serving iOS, Android and web from a single model
  • E-commerce catalogues — products, variants, categories and imagery consumed by a storefront
  • Multi-locale content hubs — locale variants with role-scoped teams

Dependencies for Strapi

  • Strapi 5 (@strapi/strapi), built from gridalpha/strapi-railway — application and admin panel
  • PostgreSQL 18 (ghcr.io/railwayapp-templates/postgres-ssl:18) — all content, users and permissions
  • Railway object storage bucket — media uploads and their generated image variants

Environment Variables Reference

VariablePurpose
APP_KEYSComma-separated session signing keys
ADMIN_JWT_SECRET, JWT_SECRETSign admin sessions and API tokens
API_TOKEN_SALT, TRANSFER_TOKEN_SALTSalt generated tokens
ENCRYPTION_KEYEncrypts sensitive values at rest
DATABASE_URLPostgres connection string
AWS_BUCKET, AWS_ENDPOINT, AWS_REGIONObject storage location
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYObject storage credentials
AWS_SIGNED_URL_EXPIRESMedia link lifetime in seconds
PUBLIC_URLOverride canonical URL for a custom domain

The six secrets are generated at deploy time. Do not rotate them on a running instance — changing ENCRYPTION_KEY makes encrypted values unreadable, and changing the JWT secrets invalidates every admin session and API token.

Deployment Dependencies

Hardware Requirements for Self-Hosting Strapi

ResourceMinimumRecommended
CPU1 vCPU2 vCPU
RAM1 GB2 GB
StorageDatabase only (media on object storage)10 GB Postgres volume
RuntimeNode.js 22, PostgreSQL 14+Node.js 22, PostgreSQL 18

Self-Hosting Strapi

Content types in Strapi are code, not database rows. The Content-Type Builder is disabled when NODE_ENV=production, because adding a type writes files and needs a restart. Model locally and ship through git — clone the repository and run it against SQLite:

git clone https://github.com/gridalpha/strapi-railway
cd strapi-railway
npm install
cp .env.example .env
npm run develop

That opens the admin on http://localhost:1337/admin with the Content-Type Builder available. Build your types, commit the generated files and push — Railway rebuilds and they appear in the Content Manager:

git add src/api
git commit -m "add content types"
git push

To run the production image locally, build the repository's Dockerfile and pass the same variables the template sets — DATABASE_CLIENT, DATABASE_URL, APP_KEYS and the five remaining secrets.

Is Strapi Free to Self-Host?

Strapi's Community Edition is free and open source, with no cap on content types, entries, API calls or admin users. Paid tiers add single sign-on, audit logs and release management — none of which a production site requires. Self-hosting on Railway costs infrastructure only: the container, Postgres and your media storage, typically a few dollars a month for a small site.

FAQ

What is Strapi? An open-source headless CMS on Node.js. It gives editors an admin panel for structured content and developers an automatically generated REST and GraphQL API, leaving the front end to you.

What does this Railway template deploy? The Strapi 5 app built from a production Dockerfile, a managed PostgreSQL 18 database, and an object storage bucket for media. Secrets are generated at deploy time and services connected by reference.

Why does the template include Postgres instead of SQLite? SQLite would live on the container filesystem, replaced on every deploy, so content would disappear. Postgres is what Strapi recommends for production and makes concurrent editing safe.

Where do uploaded images go, and why do their URLs contain a signature? Media goes to the object storage bucket, not container disk, so it survives redeploys. The bucket is private, so Strapi serves each file through a time-limited signed URL — including to anonymous readers of the public API. Links last seven days; adjust AWS_SIGNED_URL_EXPIRES if your build caches them longer.

How do I create content types on a deployed instance? Not in production — the Content-Type Builder is disabled when NODE_ENV=production because it writes files and needs a restart. Clone the repository, run npm run develop, model your types, then commit src/api and push. Railway rebuilds and they appear.

How do I connect a Next.js or Nuxt front end? Enable find and findOne under Settings → Users & Permissions → Roles → Public, or create a scoped token under Settings → API Tokens and send it as a bearer token. Then fetch /api/?populate=*.

Can I run more than one instance of Strapi? The template ships one replica. Media lives in object storage and state in Postgres, so the app is stateless — but Strapi runs scheduled jobs in-process without leader election, so anything in config/cron.js runs once per replica. Handle that before scaling out.


Template Content

More templates in this category

View Template
Libredesk - Complete Setup
[Jul'26] Complete self-hosted omnichannel customer support desk.

codestorm
1
View Template
Paperless-ngx
Document management with OCR on Railway with PostgreSQL and Redis

INAPP
1
View Template
Instatic CMS - Postgres
Design, build and manage powerful static sites from state-of-the-art CMS

Instatic
140