media server logo

How to Build a Test App to Manage Callaba Engine on AWS

Oct 10, 2022

This tutorial is based on the real aws-react-nodejs-example project used to test and manage Callaba Engine on AWS. It is not a generic architecture article. It is a practical walkthrough of a small two-part example app: an Express server that manages AWS instance actions, and a React client that drives the Callaba Engine workflow from the browser.

If your goal is to prove the control path end to end before building a larger internal panel, this is the right scope. By the end, you should have AWS credentials configured, region-specific infrastructure values in place, the Node.js server running, the React client running, and a working flow for creating an instance, authenticating to Callaba, creating an SRT server, and opening a web player.

Clone the example project

This tutorial follows the real repository used for this setup. Clone it locally before you start so you can compare each step with the actual server and client code.

git clone https://gitlab.callabacloud.com/callaba-engine-examples/aws-react-nodejs-example.git

Open the aws-react-nodejs-example repository on GitLab

Project structure

The example repository is split into two small parts:

  • server — an Express app that works with AWS through @aws-sdk/client-ec2
  • client — a React app that talks to the local server and then calls the Callaba Engine API on the launched instance

This split is useful because it keeps AWS-facing logic and browser-facing control logic separate from the start.

Prerequisites

  • An AWS account
  • Node.js installed on your computer
  • Permission to create AWS access keys, a security group, and a key pair in the target region
  • A local machine where you can run both the server and client folders from the example project

Step 1. Create and download AWS access keys

The example uses the standard AWS credentials flow. Start by creating the access key pair for the IAM user or role you want to use during testing.

  1. Log in to the AWS Console.
  2. Open your username menu and go to Security credentials.
  3. Expand Access keys.
  4. Create a new access key.
  5. Download and store the key pair securely.
AWS security credentials screen
Open Security credentials in the AWS Console.
Create a new AWS access key
Create and download a new AWS access key pair.

Step 2. Create the AWS credentials file

On macOS and Linux, create the credentials file at ~/.aws/credentials. On Windows, create it at C:\Users\<USER_NAME>\.aws\credentials. Put the default profile in this format:

[default]
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

The server side of the example relies on the AWS SDK reading this file automatically.

Step 3. Create the security group in the correct region

The README is explicit about this: create the security group in the same region where you plan to launch the instances. If the region is wrong here, the test app quickly becomes confusing because the local code and the actual AWS environment drift apart.

The example security group uses a broad test posture:

  • Inbound: All TCP from Anywhere IPv4
  • Inbound: All UDP from Anywhere IPv4
  • Outbound: All Traffic

Once you create it, copy the security group ID and place it into server/index.js:

const SECURITY_GROUP = "sg-XXXXXXXXXXXX"; // REPLACE WITH YOUR SECURITY GROUP ID
Create security group in AWS
Start creating the security group in the target region.
Security group rules example
Apply the broad test security group rules from the example.

Step 4. Create the key pair

Create the EC2 key pair in the same AWS region. Save the key pair name and place it into the same file:

const KEY_PAIR_NAME = "your-key-pair-name"; // REPLACE WITH YOUR KEY PAIR NAME

The example server uses this constant when it launches the instance.

Create EC2 key pair
Create the EC2 key pair in the same region.

Step 5. Set the AWS region in the server

Still in server/index.js, set the region you actually chose in AWS:

const REGION = "us-east-1"; // REPLACE WITH YOUR REGION

This constant is used when the EC2 client is created:

const ec2Client = new EC2Client({ region: REGION });

Step 6. Understand what the server side does

The server app is intentionally small. It gives the client a clean local control layer for AWS actions.

Inside server/index.js, the example exposes four routes:

  • /describe — describe existing instances
  • /create — create a new AWS instance
  • /start — start the current instance
  • /stop — stop the current instance

The key creation function looks like this conceptually:

async function createInstance(name, imageId, type) {
  const instanceParams = {
    ImageId: imageId,
    InstanceType: type,
    KeyName: KEY_PAIR_NAME,
    SecurityGroupIds: [SECURITY_GROUP],
    MinCount: 1,
    MaxCount: 1,
  };

  const data = await ec2Client.send(new RunInstancesCommand(instanceParams));
  return data.Instances[0].InstanceId;
}

This is why the repo is useful as a test app: it does not try to hide the infrastructure step. It makes it explicit and easy to inspect.

Step 7. Run the server

Open the server directory and run:

npm i
node index.js

According to the example README, a healthy startup looks like this:

Your AMI creation date is - 5/3/2022

Server listening on 3001

That tells you the AWS SDK is reading credentials correctly and the local Express layer is ready.

Step 8. Run the React client

In a second terminal, move into the client folder and run:

npm i
npm start

The client package is configured with a local proxy to the Express server:

"proxy": "http://localhost:3001"

This is what lets the browser-side app talk to the local AWS control layer while still driving the actual Callaba workflow.

Step 9. Launch and observe the instance

From the client UI, create a new instance and wait for AWS to finish launching it. The README warns that once the instance reaches Running, billing starts. This is important in a test app because it is easy to forget that a successful proof of concept is still a real paid resource in AWS.

Launch instance from example client
Launch the test instance from the example client.

Step 10. Authenticate to Callaba Engine

Once the instance is running, the client authenticates to the Callaba Engine API on that instance. The example code uses the instance ID as the first password value when requesting a token:

authenticate() {
  fetch('http://' + this.state.ipAddress + '/api/auth/login', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      email: 'admin',
      password: this.state.instanceData.Reservations[this.state.instanceIndex].Instances[0].InstanceId,
    }),
  })
    .then(response => response.json())
    .then(data => {
      this.setState({ callabaToken: data.token });
    });
}

The practical point here is simple: the client stores the Callaba token and uses it to sign later requests.

Step 11. Create an SRT server

The next real workflow step in the example is creating an SRT server on the Callaba instance. This is the first meaningful media control action in the app.

createStream() {
  fetch('http://' + this.state.ipAddress + '/api/srt-servers/create', {
    method: 'POST',
    headers: {
      'x-access-token': this.state.callabaToken,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      server_name: 'Test SRT server',
      server_type: 'SERVER_TYPE_SRT',
      server_port: 1935,
      server_latency: 200,
      server_maxbw: -1,
      server_timeout: 60,
      server_rcvbuf: 48234496,
      server_active: true,
    }),
  })
    .then(response => response.json())
    .then(data => {
      this.setState({ serverId: data._id, serverState: 'server running' });
    });
}

This is the clean handoff from infrastructure control into actual streaming workflow control.

Create SRT server in the app
Create the SRT server from the running instance.

Step 12. Create a web player for the stream

To validate playback, the example creates a web player that points to the SRT server you just created.

createPlayer() {
  fetch('http://' + this.state.instanceData.Reservations[this.state.instanceIndex].Instances[0].PublicIpAddress + '/api/vod/create', {
    method: 'POST',
    headers: {
      'accept': 'application/json',
      'x-access-token': this.state.callabaToken,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      active: true,
      input: {
        input_module_id: this.state.serverId,
        input_stream_id: '',
        input_type: 'INPUT_TYPE_SRT_SOFTWARE',
      },
      vod_name: 'Test SRT player',
      vod_port: 10001,
    }),
  })
    .then(response => response.json())
    .then(data => this.setState({ playerId: data._id, playerState: 'running' }));
}

The app then generates the player URL from the instance IP and the created player ID so you can open the live stream in the browser.

Open the generated web player
Open the generated web player and confirm playback.

Other actions the example already includes

The repo does more than only create resources. It also includes the first useful lifecycle actions:

  • Stop an SRT server
  • Start a stopped SRT server
  • Delete an SRT server
  • Remove a web player
  • Create a restream
  • Remove a restream

That is why this repository is a strong test app: it starts small, but it already contains enough lifecycle control to become a real operator-side proof of concept.

Common problems and fixes

  • AWS credentials do not load: verify the credentials file path and confirm the default profile is correct.
  • Region mismatch: check the security group, key pair, and REGION constant in server/index.js.
  • The server does not start: run npm i in the server folder and verify Node.js is installed.
  • The client cannot reach the local backend: confirm the React client is still using the proxy value http://localhost:3001.
  • Callaba API actions fail after instance launch: separate AWS problems from Callaba authentication problems and verify them one at a time.
  • Costs continue after testing: stop or terminate the instance when the session is over.

Next steps

Once this example works, you no longer have to guess whether your AWS and Callaba control path can work together. You already have a real baseline project. From here, the next practical move is to replace hardcoded test values with your own workflow logic.