Railway is a cloud platform based on Heroku that makes it easy to deploy you app on the cloud. You can provision infrastructure, develop with the infrastructure locally, and deploy your app easily.
Strapi is a NodeJS based open-source CMS that's highly customizable and self-hosted.
In this tutorial, you'll learn to create a demo Strapi project and deploy it on Railway for free. You'll also pick up a few tricks along the way.
This tutorial assumes you have a basic familiarity with NPM, Git & Github, and Strapi.
Creating A Strapi Project
Create a new strapi project with the following installation script:
# using npm
npx create-strapi-app@latest demo-strapi-project
# using yarn
yarn create strapi-app demo-strapi-project
Now we should have a demo-strapi-project
folder. You can start the development server using:
npm run develop # with npm
yarn develop # with yarn
If everything goes well, you should see a login screen like this:
You can go on to create content-types with Strapi content type builder, and add contents to the new Strapi project.
Deploying on Railway
Strapi comes with an SQLite database by default, which is good for local development but not for production.
So, for the production deployment, you'll use PostgreSQL provisioned on Railway.
Create a Railway account, if you haven't already.
Create a new project on Railway. Go to Dashboard > New project
, you should see a screen similar to the image below:
Create a new Postgres database by clicking on the 'Provision PostgreSQL' option. Clicking on our created PostgreSQL service and clicking on the Variables
tab should show a screen similar to the image below:
Get the environment variables for the production deployment
Create a .env.production
file in the root folder of our Strapi project.
Copy & Paste the environment variables from the PostgreSQL database we created on Railway earlier.
Paste the environment variables from .env
that came by default at the root folder of your Strapi project over to our newly created .env.production
file.
Add a NODE_ENV=production
entry to the .env.production
file, (to let Strapi know it's a production build)
The .env.production
file should look similar to the code block below:
NODE_ENV=production
HOST=0.0.0.0 PORT=1337
APP_KEYS=1TQ+R52DVEXXXXXX==,eurEB0npfVqxWRi+XXXXX
JWT_SECRET=41115xxxxxxxxxxx56229945eda
API_TOKEN_SALT=05f84xxxxxxxxxxx0f99b3ea1
PGPASSWORD=1JxxxxxxxxxxxUBHwD PGHOST=containerxxxxxxx.railway.app
PGPORT=5931
PGUSER=postgres
PGDATABASE=railway
The next step is to configure Strapi to use the PostgreSQL database we created earlier on Railway.
Since we'll be using a PostgreSQL database, install node-postgres
, a PostgreSQL client for NodeJS, using:
npm install # npm
yarn add pg # yarn
The default database connection configuration file path is ./config/database.js
. But we want to keep the default SQLite database for local development and the remote PostgreSQL database for production. (for reasons like speed, avoid reaching your Railway free tier limit).
Strapi has a feature that lets you set different configurations for specific environments using ./config/env/{environment}/{config-filename.js}
naming and structure convention.
To do this:
- Create an env
folder in the config folder at the root of your Strapi project folder.
- Create a production
folder in our created env
folder (Because you're configuring for the production environment).
- Create a database.js
file in the new production
folder (Since we're defining a database configuration) i.e ./config/env/production/database.js
The content of your new database.js
file should look similar to the code block below:
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('PGHOST', '127.0.0.1'),
port: env.int('PGPORT', 5931),
database: env('PGDATABASE', 'railway'),
user: env('PGUSER', 'postgres'),
password: env('PGPASSWORD', 'password'),
ssl: env.bool(true),
},
},
});
To confirm everything goes well, run a production build with:
# npm
ENV_PATH=./.env.production NODE_ENV=production npm run start
# yarn
ENV_PATH=./.env.production NODE_ENV=production yarn start
If everything goes well, you should be able to open the admin panel at http://0.0.0.0:1337/admin
:
The next step is to make your Strapi project a git repository and push to Github. So that we can deploy on Railway from our repo.
Go back to your project on Railway, Click on the New
button, choose the Github Repo option, then you should choose your Strapi app repo.
At this point, the build will fail for two reasons:
- Because Railway resolved to a node version that Strapi doesn't support. (Strapi doesn't support odd-number releases of Node e.g. v13, v15. From the log, Strapi is picking up v15. Yikes).
- We haven't added our environment variables to Railway. Strapi needs these to run.
To fix the first issue, change the loose node version specified by default in package.json
of your Strapi project.
//package.json
"engines": {
"node": ">=12.x.x <=16.x.x",
"npm": ">=6.0.0"
},
To something more specific like v16.4.2 (a LTS version of Node)
//package.json
"engines": {
"node": "16.14.2",
"npm": ">=6.0.0"
},
Now commit and push. Railway auto deploys on new git commits, our build will still fail as you haven't provided the necessary enviroment variables.
Go to the Variables
tab of the Strapi deployment on Railway. Click on the 'Bulk Import' button. Paste in all the contents of the .env.production
file you created earlier.
If everything goes well, our build should now be successful. You should be assigned a Service domain like project-name.up.railway.app. which you can go on to customize.
Top comments (16)
Hey Yinka, thanks for your tutorial!
I'm encountering a problem when I run the production build with:
ENV_PATH=./.env.production NODE_ENV=production yarn start
Strapi tells me…
Do you have a solution? Thanks again!
When you change the the host from 0.0.0.0 to 127.0.0.1, you need to rebuild your strapi app again, then do npm start.
So basically:
npm run build
ENV_PATH=./.env.production NODE_ENV=production npm run start
This was perfect for what I was looking for. Thanks for sharing.
Now i have connected my strapi app to the database and my data is persisting in between builds...except for images. Guess we need to use cloudinary for that.
hey, how do you persist data between local development and production on Railway? can you please explain?
hi Mario,
Well once I setup the production build of Strapi I use that to build out the frontend. I am not using the same data on production and my local instance of Strapi.
Thanks a lot for this! I've had trouble getting my backend up and running on railway. I still have problems though. Eventhough the build is successful it gives me this in the logs:
Create your first administrator 💻 by going to the administration panel at:
┌───────────────────────────┐
│ 0.0.0.0:1337/admin │
└───────────────────────────┘
That page can't be reached. I don't see an adress for a global page either?
Got any clue on what im doing wrong here?
running ENV_PATH=./.env.production NODE_ENV=production yarn start
results in
'ENV_PATH' is not recognized as an internal or external command,
operable program or batch file.
any idea what might wrong ?
Very helpful -- not a lot of documentation on this out there. Thanks!
I followed all the steps and deployment was successful, I just dont get a Service domain. It only shows 0.0.0.0:1337. Any help would be appreciated
Click on
Settings
and look forDomains
. You'll be able to get a url there. I hope this helps!Thank you @yinks!
Another article about connecting tha backend service to a frontend service would be great. I am struggling to make requests from my frontend project to the backend.
I'd keep this on my todo. Thank you for the feedback
after pushing to production, all my prev content disappears. Any one know why it happened?
I am struggling deploying the project since I have the backend in the root directory and the Vue frontend in /frontend directory. Any clues about how to deploy this?
I believe the deployment should work all right, as the build tool will ignore the
frontend
directory.