Skip to content
On this page

Installing Runnable Server

Overview

Runnable Server is a great way to build a scalable admin tool. You can connect many clients, for example, a user-service and an email-service that can stream their actions to a central location using the Runnable SDK. This is great for services not exposed to the public internet and for services that may be deployed with multiple instances.

Deploying the Runnable Server

You can deploy runnable as a dockerized container.

bash
docker pull ghcr.io/kineticio/runnable:latest
docker pull ghcr.io/kineticio/runnable:latest

Pin Version

It is recommended to pin to a particular version. You can find the latest package version here.

Settings up the required env variables

Environment VariableDescriptionHow to Generate
RUNNABLE_BASE_URLThe base URL for your Runnable instance. This has a default of /admin for Runnable Mini, but should override to be /.Should just provide '/'
RUNNABLE_SECRETA secret key used for encrypting the user's cookie session.Run openssl rand -hex 32 in your terminal
RUNNABLE_AUTH_SECRETA secret key used during the handshake between a Runnable Server and Runnable SDK Client.Run openssl rand -hex 32 in your terminal
RUNNABLE_AUTH_PROVIDER_GOOGLE_CLIENT_IDThe client ID for the Google authentication provider.Generated by Google.
RUNNABLE_AUTH_PROVIDER_GOOGLE_CLIENT_SECRETThe client secret for the Google authentication provider.Generated by Google.
RUNNABLE_AUTH_PROVIDER_GOOGLE_HOSTNAMEThe hostname for the Google authentication provider.E.g. https://admin.company-name.com
RUNNABLE_AUTH_PROVIDER_GOOGLE_HDThe hosted domain for the Google authentication provider. Setting this will limit the email domain allowed to login.Provided by Google.

Installing the Runnable SDK

With npm

bash
npm install -D @runnablejs/sdk
npm install -D @runnablejs/sdk

or with yarn

bash
yarn add -D @runnablejs/sdk
yarn add -D @runnablejs/sdk

or with pnpm

bash
pnpm add -D @runnablejs/sdk
pnpm add -D @runnablejs/sdk

Setting in your server

ts
// index.ts
import { userInfo } from 'node:os';
import { RunnableWs } from '@runnablejs/sdk';
import { getUsers, getTeams, assignTeam } from './db';
import { auth } from './auth';

new RunnableWs(actions, {
  // Your admin portal. This can be a staging, development, or local URL.
  runnableHost: 'wss://admin.company-name.com',
  // Some domain displayed to the user and used to dedupe among multiple instances of the same server.
  namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
  // Can be a custom logger or defaults to console.
  logger: console,
  // Shared auth token between Runnable client nad Runnable server.
  token: process.env.RUNNABLE_AUTH_SECRET,
}).start();
// index.ts
import { userInfo } from 'node:os';
import { RunnableWs } from '@runnablejs/sdk';
import { getUsers, getTeams, assignTeam } from './db';
import { auth } from './auth';

new RunnableWs(actions, {
  // Your admin portal. This can be a staging, development, or local URL.
  runnableHost: 'wss://admin.company-name.com',
  // Some domain displayed to the user and used to dedupe among multiple instances of the same server.
  namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
  // Can be a custom logger or defaults to console.
  logger: console,
  // Shared auth token between Runnable client nad Runnable server.
  token: process.env.RUNNABLE_AUTH_SECRET,
}).start();

Example with Next.js

Create the providers for the RunnableWorkflows.

ts
// actions.provider.ts

import { FactoryProvider, Provider } from '@nestjs/common';
import { RunnableWorkflows, RunnableAppContext } from '@runnablejs/express';
import { AppService } from './app.service';

export const ActionsProvider: FactoryProvider<RunnableWorkflows> = {
  provide: 'RUNNABLE_ACTIONS',
  inject: [DatabaseService],
  useFactory: (database: DatabaseService) => ({
    assign_user_to_team: {
      // ...
    },
    create_user: {
      // ...
    },
  }),
};
// actions.provider.ts

import { FactoryProvider, Provider } from '@nestjs/common';
import { RunnableWorkflows, RunnableAppContext } from '@runnablejs/express';
import { AppService } from './app.service';

export const ActionsProvider: FactoryProvider<RunnableWorkflows> = {
  provide: 'RUNNABLE_ACTIONS',
  inject: [DatabaseService],
  useFactory: (database: DatabaseService) => ({
    assign_user_to_team: {
      // ...
    },
    create_user: {
      // ...
    },
  }),
};

Create the module for the Actions.

ts
// actions.module.ts
import { Module } from '@nestjs/common';
import { ActionsProvider } from './actions.provider';

@Module({
  imports: [DatabaseModule],
  providers: [ActionsProvider],
})
export class ActionsModule {}
// actions.module.ts
import { Module } from '@nestjs/common';
import { ActionsProvider } from './actions.provider';

@Module({
  imports: [DatabaseModule],
  providers: [ActionsProvider],
})
export class ActionsModule {}

Start your Next.js application with Actions.

ts
// main.ts
import { installRunnable } from '@runnablejs/express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Setup Runnable
  const actions = app.get('RUNNABLE_ACTIONS');
  const config = new RunnableWs(actions, {
    // Your admin portal. This can be a staging, development, or local URL.
    runnableHost: 'wss://admin.company-name.com',
    // Some domain displayed to the user and used to dedupe among multiple instances of the same server.
    namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
    // Can be a custom logger or defaults to console.
    logger: app.get(Logger),
    // Shared auth token between Runnable client nad Runnable server.
    token: process.env.RUNNABLE_AUTH_SECRET,
  }).start();

  await app.listen(3000);
}
bootstrap();
// main.ts
import { installRunnable } from '@runnablejs/express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Setup Runnable
  const actions = app.get('RUNNABLE_ACTIONS');
  const config = new RunnableWs(actions, {
    // Your admin portal. This can be a staging, development, or local URL.
    runnableHost: 'wss://admin.company-name.com',
    // Some domain displayed to the user and used to dedupe among multiple instances of the same server.
    namespace: process.env.NODE_ENV === 'development' ? `${userInfo().username}_local_development` : 'users',
    // Can be a custom logger or defaults to console.
    logger: app.get(Logger),
    // Shared auth token between Runnable client nad Runnable server.
    token: process.env.RUNNABLE_AUTH_SECRET,
  }).start();

  await app.listen(3000);
}
bootstrap();

Released under the MIT License.