In this post, we will walk through deploying hyper63 on render.com. Render.com is a cloud service that is built on top of kubernetes. The service abstracts all of the cloud configuration management challenges and gives you a clean application deployment platform. You can deploy static sites, app servers, cron jobs and private services. Render gives you the ability to setup private networks specified by teams and gives you all the great features of containers and the management of containers leveraging infrastructure as code markup and git repositories.

Prerequisites

Before we get started, you may want to signup for an account with render, https://render.com/register

NOTE: this tutorial is going to walk through setting up a service using render services that will cost money to host. If you want to check out "hyper63" for free go to https://github.com/hyper63/tour and use our playground service.

Setting up the hyper63 config

hyper63 is a modular system, which means you have to specify all of the adapters you want to use with hyper63 via a configuration file. While this may seem to be tedious, it gives you flexibility and extensibility. For our configuration, we are going to use the following services:

  • CouchDb for data port
  • Redis for cache port
  • ElasticSearch for search port
  • MinIO for storage port

Create a new folder called hyper63-micro

mkdir hyper63-micro
cd hyper63-micro

Initialize the project as a NodeJS project, using yarn

npm install --global yarn@1.x
yarn init -y

hyper63

Install the hyper63 modules:

yarn add @hyper63/core
yarn add @hyper63/app-express
yarn add @hyper63/adapter-couchdb
yarn add @hyper63/adapter-redis
yarn add @hyper63/adapter-minio
yarn add @hyper63/adapter-elasticsearch

Modify the package.json to support ESM modules

{
  ...
  "type": "module"
}

Create an index.js file to start the service.

import config from './hyper63.config.js'
import hyper63 from '@hyper63/core'

hyper63(config)

Create the hyper63 config file

  
import express from '@hyper63/app-express'
import couchdb from '@hyper63/adapter-couchdb'
import redis from '@hyper63/adapter-redis'
import es from '@hyper63/adapter-elasticsearch'
import minio from '@hyper63/adapter-minio'
import jwt from './jwt.js'


const COUCH = `http://${process.env.USER}:${process.env.PASSWORD}@${process.env.COUCHDB_HOST}:5984`
const REDIS = `redis://${process.env.REDIS_HOST}`
const ES = `http://${process.env.SEARCH_HOST}:9200`
const MINIO = `http://${process.env.USER}:${process.env.PASSWORD}@${process.env.MINIO_HOST}:9000`

export default {
  app: express,
  adapters: [
    { port: 'data', plugins: [couchdb({url: COUCH })]},
    { port: 'cache', plugins: [redis({url: REDIS})]},
    { port: 'search', plugins: [es({url: ES})]},
    { port: 'storage', plugins: [minio({url: MINIO})]}
  ],
  middleware: [jwt]
}

We will use jwt middleware to secure our service.

Install express-jwt

yarn add express-jwt

create jwt.js file

import jwt from 'express-jwt'

export default app => {
  app.use(jwt({
    secret: process.env.SECRET, 
    algorithms: ['HS256']
  }).unless({path: ['/']}))

  app.use((err, req, res, next) => {
    if (err.name === 'UnauthorizedError') {
      res.status(401).send({ok: false, msg: 'not authorized'})
    }
  })

  return app
}

Couchdb Service

In order to create a couchdb service we need to create a docker file.

make a directory called couchdb and in that directory create a file called Dockerfile

mkdir couchdb
touch couchdb/Dockerfile

edit couchdb/Dockerfile

FROM couchdb:3.1.1

RUN echo '[couchdb]' > /opt/couchdb/etc/local.d/10-single-node.ini
RUN echo 'single_node=true' >> /opt/couchdb/etc/local.d/10-single-node.ini

ElasticSearch Service

In order to create an elasticsearch service we need a dockerfile.

make a directory called elastic and in that directory create a file called Dockerfile

mkdir elastic
touch elastic/Dockerfile

edit elastic/Dockerfile

# The official Elasticsearch Docker image
FROM elasticsearch:7.9.3 
# Copy our config file over
COPY --chown=1000:0 config/elasticsearch.yml /usr/share/elasticsearch/config/elasticsearch.yml

# Allow Elasticsearch to create `elasticsearch.keystore`
# to circumvent https://github.com/elastic/ansible-elasticsearch/issues/430
RUN chmod g+ws /usr/share/elasticsearch/config

USER 1000:0

create a sub folder called config and a file called elasticsearch.yml

mkdir elastic/config
touch elastic/config/elasticsearch.yml

edit elastic/config/elasticsearch.yml

cluster.name: "elastic"
# bind to all network interfaces
network.host: 0.0.0.0

Redis

create a folder called redis and a Dockerfile

mkdir redis
touch redis/Dockerfile

edit redis/Dockerfile

FROM redis:6-alpine

COPY redis.conf .

ENTRYPOINT ["redis-server", "./redis.conf"]

create another file called redis/redis.conf

You can copy the redis.conf from here: https://raw.githubusercontent.com/hyper63/micro-for-render/master/redis/redis.conf

MinIO

create a folder called minio and a Dockerfile

mkdir minio
touch minio/Dockerfile

edit minio/Dockerfile

FROM minio/minio:RELEASE.2021-02-14T04-01-33Z

ENTRYPOINT ["minio", "server", "/data"]

Render.yaml

create a file called render.yaml

We need to add all of these services to the render.yaml which will instruct render on how to deploy and connect our services in a private render team.

services:
- type: web
  name: hyper63
  env: node
  buildCommand: yarn
  startCommand: yarn start
  envVars:
    - key: SECRET
      generateValue: true
    - key: USER
      fromService:
        name: couchdb
        type: pserv
        envVarKey: COUCHDB_USER
    - key: PASSWORD
      fromService:
        name: couchdb
        type: pserv
        envVarKey: COUCHDB_PASSWORD
    - key: COUCHDB_HOST
      fromService:
        name: couchdb
        type: pserv
        property: host
    - key: REDIS_HOST
      fromService:
        name: redis
        type: pserv
        property: hostport
    - key: SEARCH_HOST
      fromService:
        name: elasticsearch
        type: pserv
        property: host
    - key: MINIO_HOST
      fromService:
        name: minio
        type: pserv
        property: host
- type: pserv
  name: couchdb
  env: docker
  plan: standard
  dockerfilePath: ./couchdb/Dockerfile
  disk:
    name: couchdata
    mountPath: /opt/couchdb/data
    sizeGB: 50
  autoDeploy: false
  envVars:
    - key: COUCHDB_USER
      value: admin
    - key: COUCHDB_PASSWORD
      value: password
- type: pserv
  name: redis
  env: docker
  dockerfilePath: ./redis/Dockerfile
  dockerContext: ./redis
  plan: standard
  autoDeploy: false
  disk:
    name: redisdata
    mountPath: /var/lib/redis
    sizeGB: 10
- type: pserv
  name: elasticsearch
  env: docker
  plan: standard
  dockerfilePath: ./elastic/Dockerfile
  dockerContext: ./elastic
  disk:
    name: esdata
    mountPath: /usr/share/elasticsearch/data
    sizeGB: 10
  autoDeploy: false
  envVars:
    - key: ES_JAVA_OPTS
      value: "-Xms512m -Xmx5123m"
    - key: discovery.type
      value: single-node
    - key: cluster.name
      value: elastic
- type: pserv
  name: minio
  env: docker
  plan: standard
  dockerfilePath: ./minio/Dockerfile
  dockerContext: ./minio
  disk:
    name: miniodata
    mountPath: /data
    sizeGB: 20
  autoDeploy: false
  envVars:
    - key: MINIO_ACCESS_KEY
      value: admin
    - key: MINIO_SECRET_KEY
      value: password

Add Readme

# README

This is a template repository for running hyper63 on render.

* It uses [Render Disks](https://render.com/docs/disks) for persistent storage.
* hyper63 runs in your [Render private network](https://render.com/docs/private-services) so it isn't exposed to the public internet.

## Deployment

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy)

## Environment

When deployed, go to Environment and grap the SECRET value, this secret will be used to validate JWT Tokens for 
the service.

> NOTE: this deployment plan will create 5 services on render, 4 will cost $15/mo and 1 will cost $7/mo.

Create Repository on Github

git init
echo node_modules > .gitignore
git add .
git commit -m "first commit"
gh repo create hyper63-micro
git push origin master

Sync to Render

In Github, go to the readme view and click the deploy to render button, then in Render, choose this repository and follow the instructions.

Summary

This post documents the steps to deploy a micro stack of hyper63, but if you don't want to go through all of this, you can choose to use https://github.com/hyper63/micro-for-render

Maybe fork the repo and update each docker file with the latest container versions then deploy.