Deploying hyper63 on Render.com
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.