How to create and deploy a Strapi project on Railway
Tags: strapi, node, serverless, cloud
Published: 2022-04-08 14:51:31

[Railway](railway.app) 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](https://strapi.io) 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:

```bash
# 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:

```bash
npm run develop # with npm
 
yarn develop # with yarn
```

If everything goes well, you should see a login screen like this:
![Strapi login screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7dy7ic6zmdxogzytumnu.png)

You can go on to create content-types with [Strapi content type builder](https://docs.strapi.io/user-docs/latest/content-types-builder/introduction-to-content-types-builder.html), and add contents to the new Strapi project.

![Strapi Content Manager Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwu46nihe4m2u5q1c88y.png)

## 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](https://www.postgresql.org/) provisioned on Railway.

Create a [Railway account](https://railway.app), 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nsvat9vrcjkhjgiab7uv.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7br87vlx33av342zq5qx.png)

### 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:

```plain
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:

```bash
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:

```js
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:

```bash
# 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`:
![Serving Production mode of Strapi locally Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftd99gnavm1benmrsszy.png)

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](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment.html#general-guidelines) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6r5j5uifgr4lsq157p8.png)

To fix the first issue, change the loose node version specified by default in `package.json` of your Strapi project.

```json
//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)

```json
//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.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51x353vxog8r747r4isi.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6od2xebv9gh3ncolr6x.png)

### Resources

- [Database configuration](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/required/databases.html#configuration-structure)
- [Configuration using environment variables](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables)
- [Railwa docs - NodeJS](https://docs.railway.app/deploy/nodejs)