Deploy Strapi 5 | Headless CMS Whose Uploads Survive a Redeploy
Self-host Strapi 5 on Railway — Postgres, uploads that survive a redeploy.
Postgres
Just deployed
/var/lib/postgresql/data
Just deployed
/app/public/uploads
Deploy and Host Strapi on Railway
Strapi 5, the open-source headless CMS, on Postgres, with uploaded media on a volume mounted where Strapi actually writes it, so images survive a redeploy.
Nothing to fill in. Open /admin on the domain and create the first administrator.
About Hosting Strapi
Two services:
- Strapi 5.56, built from ak40u/strapi-railway-starter: the admin panel and the REST API, with a volume for the media library (public)
- Postgres 17: content types and entries, on its own volume and on the private network only
Model your content types in the admin panel's Content-Type Builder, then read them through /api/.
Common Use Cases
- The backend of a website or app built with Next.js, Nuxt, Astro or a mobile client.
- A content hub for marketing pages, blog posts and product data edited by non-developers.
- An internal admin panel over structured data, with roles and permissions.
Dependencies for Strapi Hosting
Deployment Dependencies
- Strapi 5.56 (MIT, Community Edition) on Node.js 22, built from the starter repository's Dockerfile
- Postgres
postgres:17.11-alpine
Implementation Details
- Uploads land on the volume. The common Strapi template mounts its volume at
/public/uploads, but the app runs from/appand Strapi's local upload provider writes to/app/public/uploads. Every image uploaded through the admin panel goes to the container's own disk beside an empty volume and disappears on the next deploy. Here the volume is mounted at/app/public/uploads. - The admin panel is built into the image, so a deploy goes live without compiling the panel inside a running service.
- Strapi knows it is behind a proxy.
proxy.koatrusts Railway'sX-Forwarded-*headers, so requests count as https and admin cookies are marked secure;PUBLIC_URLgives the panel and media URLs the real domain. - A real health check.
/_healthis Strapi's own endpoint, and Railway waits for it before switching traffic. - Postgres is private, with no TCP proxy.
Configuration
All six Strapi secrets and the Postgres password are generated. To serve media from a CDN or object storage instead of the volume, install an upload provider such as @strapi/provider-upload-aws-s3 in the repository and configure it in config/plugins.js.
Verification
Deployed from this template into an empty project, both services starting at once: live in a little over two minutes, /_health answers 204 and the admin panel is waiting for its first administrator. With the service capped at 0.5 GB, Strapi used about 0.17 GB. Locally, on the same image and a root-owned volume at the same path: registering the administrator, uploading an image, and the image still being served after the container was recreated.
Why Deploy Strapi on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Strapi on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
Template Content
Postgres
postgres:17.11-alpine