Deploying Nodewood
Tags: node, devops, cloud
Published: 2021-06-08 03:54:02

[*This was originally  [posted to a Github discussion on the Nodewood repository](https://github.com/Nodewood/issues/discussions/3) ; adding here for posterity.*]

I recently deployed a vanilla instance of [Nodewood](https://nodewood.com/), a JavaScript SaaS Starter Kit, to the cloud. I picked Render.com but this might help with other platforms (PaaS).

Things I set up before deploying:
1. A fresh Nodewood project running locally according to the Guide (great docs!)
2. My Nodewood project pushed to private Github repo (with changes outlined below)
3. Stripe account (activated, so I have production API keys)
4. Render account linked to my Github account
5. A Postgres db from Render (an addon for $7/mo)

This looks like a lot of work, but it's fairly quick-n-easy.

## Project changes

#### `knexfile.js`

❗ Add `knexfile.js` to `.gitignore` so that it won't be a part of the production codebase. Knex configuration specific to production will be added to the Render service configuration (covered below).  
Run `> git rm knexfile.js` if it has already been added to the repo.

#### `package.json`

Add some helpful commands to `scripts` for production use on Render:
```diff
+    "production:build": "yarn && yarn production:migrate && yarn production:stripe-sync && yarn production:build-ui",
+    "production:migrate": "knex migrate:latest --env production",
+    "production:stripe-sync": "npx @nodewood/cli stripe:sync --no-confirm",
+    "production:build-ui": "NODE_ENV=production yarn build-ui",
+    "production:start": "node app/api/api.js",
```
These are simple helpers that can be edited later if needed. Render will be configured to run these as a part of the build and deploy process.

## Render Service Setup

Create a new "Web Service" linked to the (private) Github repo. $7/mo

### Settings

❗ Change "Environment" option to "Node". Render will autodetect "Docker" but in this case it would add some unneeded overhead.

Build command: `yarn production:build` the custom script added to package.json that will run with each deploy

Start command: `yarn production:start` run the API

### Advanced Settings

#### Environment variable:

key: `NODE_ENV`, value: 'production' -- just to be sure our code knows where it's at.

#### 3 Secret files:

1. `.env`: copied from local project with updated `DB_` variables for the Render database and updated production `pk_` and `sk_` keys from Stripe
2. `.nodewood.js`: copied exactly from local project 👍🏻 
3. `knexfile.js`: with only a production object containing the Render database details. Looks similar to:

```js
module.exports = {
  production: {
    client: "postgresql",
    connection: {
      host: "Hostname from Render database",
      database: "myapp",
      user: "myapp",
      password: "generatedpassword"
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      tableName: "knex_migrations",
      stub: "migrations.stub",
      directory: ["./wood/migrations", "./app/migrations"]
    }
  }
};
```

### Deploy 🚀 

Commit and push your main git branch, Render will handle the rest.

## Using your Nodewood App

1. Visit your Nodewood app (probably a .onrender.com URL) to see the static content (from `./www/dist/`)
2. Sign up for an account
3. Edit the new user record in the database so that `email_confirmed` = TRUE and `account_type` = "admin". (I use Postico.app on my Mac to connect to the Render database to do this)
4. Visit the admin section of your Nodewood application in the browser!

This is as far as I've gotten so far, but from here I can just focus on my idea and not worry about deploying.

## Notes/Ideas:

- I didn't check if Knex could be configured from .env or similar -- this would eliminate the need for a production `./knexfile.js`
- No mailer was set up yet.
- It's probably possible to deploy with Docker on Render, but that kind of defeats the purpose here 😄 
- I didn't check how many Postgres connections are allowed by Render's db service. So I may need to update the production Knex `pool` configuration