Skip to content

Sidecars

norsk-ctl launches each instance as a docker-compose project (named by the instance id) running the services its product template defines — for Studio that’s studio and media. Sidecars are an admin-only escape hatch that lets you merge additional services: into that project — companion containers (event subscribers, custom sources, glue services) that share the instance’s lifecycle.

Under the hood the sidecar is just a docker-compose file merged into the instance’s project, so it can also override values on existing services if you need to — but the primary use case (and the name) is companion containers.

  • You have a small auxiliary container that needs to talk to the instance’s studio or media service and come up/down with the instance.
  • You want to depend on studio: condition: service_healthy so the sidecar only starts after Studio is responsive.
  • The shape of the sidecar varies enough that hard-coding it into norsk-ctl would be a leaky abstraction.

If you’re spinning up a generic SRT/RTMP source pump, see norsk-ctl source instead — that’s the typed path.

  1. Drop your sidecar file under <workingDirectory>/<somewhere>/<sidecar>.yaml.
  2. Pass --sidecars <path> (repeatable) on norsk-ctl instance launch-template. Relative paths resolve against the working directory; absolute paths are accepted as-is.
  3. norsk-ctl validates each file exists, then appends it to the docker compose -f chain after the product template compose and the runner override. Sidecar files merge last, so they can override service definitions if needed.
  4. The sidecar paths are persisted with the launch config, so instance relaunch keeps the sidecars.

Example: a Node sidecar that subscribes to Studio’s firehose

Section titled “Example: a Node sidecar that subscribes to Studio’s firehose”

This mirrors a real integration — an LLM-backed reasoning processor in Studio emits events, and a small Node container POSTs them to an external HTTP endpoint.

<workingDirectory>/sidecars/connector.yaml:

services:
connector:
image: my-org/scte35-connector:1.0.0
depends_on:
studio:
condition: service_healthy
environment:
STUDIO_WS_URL: ws://studio:8000/live/firehose
DAZN_CHANNEL_ID: TX09
DRY_RUN: "1"
volumes:
- /path/to/secrets/dazn.json:/run/secrets/dazn.json:ro
restart: unless-stopped

The sidecar joins the instance’s compose project, so it addresses the template’s services by name (studio, media) and compose names its container <instance-id>-connector-1 — project-name isolation keeps multiple instances sharing the same sidecar file apart. Don’t set container_name yourself; a pinned name can only exist once, so the file would no longer be reusable across instances.

Launch:

Terminal window
norsk-ctl instance launch-template my-stream \
--template my-product \
--sidecars sidecars/connector.yaml

After launch, norsk-ctl instance describe my-stream lists the sidecar alongside the studio + media containers, and the UI’s instances list renders it.

Each instance’s services sit on two networks: the compose project’s own default network (per-instance, where service names like studio and media resolve unambiguously) and the shared norsk-net bridge (the external: true network the proxy uses to reach instances). A sidecar with no networks: key joins the project’s default network, which is what you want for talking to its own instance’s services. Add networks: [norsk-net] only if the proxy or another instance must reach the sidecar — on the shared bridge, address containers by their full name (<id>-studio-1) since bare service names collide across instances.

norsk-ctl doesn’t yet have a logs subcommand for sidecar containers. Use docker logs against the compose-named container directly:

Terminal window
docker logs my-stream-connector-1 -f

The web UI’s logs view targets media/studio only — sidecar logs are docker-side for now.

Sidecar files are interpolated against the same .env the rest of the instance’s compose project sees: the product template’s parameters (defaults plus whatever you passed with --param, e.g. INSTANCE_NAME on Studio templates) and any runner-allocated port parameters the template declares. ${INSTANCE_NAME} in a sidecar file therefore resolves exactly as it does in the template’s own compose.yml. See Products & Templates for where parameters come from.

  • Don’t pin container_name. Compose’s project-name isolation already namespaces sidecar containers per instance (<id>-<service>-1); pinning a name breaks reusing the same sidecar file across instances.
  • No schema enforcement. norsk-ctl only checks the file exists — docker compose does the rest at launch time. If your sidecar has a YAML typo or references an unknown env var, you’ll see compose’s error, not a norsk-ctl validation message.
  • Image pulling. Pre-pull / rebuild your sidecar image before launch; norsk-ctl doesn’t preflight sidecar images the way it does for the template’s own images.
  • Removed instances. norsk-ctl instance delete issues docker compose down against the project, which removes sidecars too — including any volumes declared without external references.
  • Overrides, not just additions. Because the file is merged into the compose project, you can also override existing service config (env vars on studio/media, extra volumes). Use sparingly — that path bypasses norsk-ctl’s assumptions.