Self-host Strapi with Postgres and File Uploads
Strapi is an open-source headless CMS that provides an admin panel for content management and a REST/GraphQL API for delivering content to frontends. It supports custom content types, role-based access, and plugin extensions.
This guide covers deploying Strapi on Railway with a Postgres database and persistent file storage.
What you will set up
- A Strapi instance with the admin panel
- A Postgres database for content storage
- Persistent file uploads via a Railway Volume or Storage Bucket
- A public domain for the API and admin panel
One-click deploy from a template
Railway has a Strapi template that provisions the full setup:
After deploying, generate a domain for the Strapi service and open /admin to create your first admin user.
It is recommended to eject from the template to get a copy of the repository on your own GitHub account.
If you prefer to set things up manually, continue with the steps below.
Deploy manually
1. Create a new Strapi project
Select Postgres as the database during setup. Push the project to a GitHub repository.
2. Create the Railway project and database
- Create a new project on Railway.
- Add a PostgreSQL database: click + New, then Database, then PostgreSQL.
- Deploy the Strapi app: click + New, then GitHub Repo, and select your repository.
3. Configure environment variables
Add the following variables to the Strapi service:
Generate the required secret keys and add them:
Generate random strings with:
4. Generate a domain
Navigate to Networking in the service settings and generate a domain. Open https://your-domain.railway.app/admin to access the admin panel.
Persistent file storage
By default, Strapi stores uploaded files on the local filesystem. On Railway, the filesystem is ephemeral, meaning uploads are lost on each deploy.
Option 1: Railway Volume
Attach a Volume to the Strapi service mounted at /app/public/uploads. Files persist across deploys.
- In your Strapi service, go to Settings, then Volumes.
- Add a volume with the mount path
/app/public/uploads.
This is the simplest option. The tradeoff is that volumes are tied to a single service instance.
Option 2: Storage Bucket (S3-compatible)
For production use, configure Strapi's S3 upload provider with a Railway Storage Bucket:
- Create a bucket in your Railway project.
- Install the S3 upload provider:
- Configure
config/plugins.js:
- Add the bucket credentials to your Strapi service variables.
Connecting a frontend
Strapi exposes a REST API at /api and an optional GraphQL API via a plugin. Point your frontend to the Strapi service's public domain:
If your frontend runs in the same Railway project, use private networking instead:
Next steps
- Storage Buckets - Configure S3-compatible storage.
- Volumes - Attach persistent storage to a service.
- Private Networking - Connect frontend and CMS internally.
- Manage environment variables - Handle API URLs across services.