DEV Community

Yinka Adedire
Yinka Adedire

Posted on

How to create and deploy a Strapi project on Railway

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

If everything goes well, you should see a login screen like this:
Strapi login screenshot

You can go on to create content-types with Strapi content type builder, and add contents to the new Strapi project.

Strapi Content Manager Screenshot

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: 
Railway dashboard Screenshot

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:
Railway PostgresSQL Service Screenshot

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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),
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

If everything goes well, you should be able to open the admin panel at http://0.0.0.0:1337/admin:
Serving Production mode of Strapi locally Screenshot

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.

Build Failure on Railway

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"
 },
Enter fullscreen mode Exit fullscreen mode

To something more specific like v16.4.2 (a LTS version of Node)

//package.json
"engines": {
  "node": "16.14.2",
  "npm": ">=6.0.0"
 },
Enter fullscreen mode Exit fullscreen mode

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.
Image description

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.

Strapi deploy screenshot

Resources

Top comments (15)

Collapse
 
imcorentin profile image
Corentin Bernadou

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…

An error occurred while requesting the API

Do you have a solution? Thanks again!

Collapse
 
davemarong profile image
Dave Kjell Marong

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

Collapse
 
fpigeonjr profile image
Frank Pigeon Jr. 🇵🇦🇺🇸

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.

Collapse
 
cmario92 profile image
cmario

hey, how do you persist data between local development and production on Railway? can you please explain?

Collapse
 
fpigeonjr profile image
Frank Pigeon Jr. 🇵🇦🇺🇸

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.

Collapse
 
imoempire profile image
Isaac Obeng • Edited

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 ?

Collapse
 
rachaellynn profile image
rachaellynn

Very helpful -- not a lot of documentation on this out there. Thanks!

Collapse
 
arod1207 profile image
Armando Rodriguez

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

Collapse
 
anohene1 profile image
Isaac Anohene

Click on Settings and look for Domains. You'll be able to get a url there. I hope this helps!

Collapse
 
muriukialex profile image
Alex

Thank you @yinks!

Collapse
 
frontendcrypto profile image
frontendcrypto

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.

Collapse
 
yinks profile image
Yinka Adedire

I'd keep this on my todo. Thank you for the feedback

Collapse
 
stanislavlyu profile image
Stanislav

after pushing to production, all my prev content disappears. Any one know why it happened?

Collapse
 
frontendcrypto profile image
frontendcrypto

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?

Collapse
 
yinks profile image
Yinka Adedire

I believe the deployment should work all right, as the build tool will ignore the frontend directory.