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.
When to use it
Section titled “When to use it”- You have a small auxiliary container that needs to talk to the instance’s
studioormediaservice and come up/down with the instance. - You want to depend on
studio: condition: service_healthyso the sidecar only starts after Studio is responsive. - The shape of the sidecar varies enough that hard-coding it into
norsk-ctlwould 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.
How it works
Section titled “How it works”- Drop your sidecar file under
<workingDirectory>/<somewhere>/<sidecar>.yaml. - Pass
--sidecars <path>(repeatable) onnorsk-ctl instance launch-template. Relative paths resolve against the working directory; absolute paths are accepted as-is. norsk-ctlvalidates each file exists, then appends it to thedocker compose -fchain after the product template compose and the runner override. Sidecar files merge last, so they can override service definitions if needed.- The sidecar paths are persisted with the launch config, so
instance relaunchkeeps 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-stoppedThe 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:
norsk-ctl instance launch-template my-stream \ --template my-product \ --sidecars sidecars/connector.yamlAfter launch, norsk-ctl instance describe my-stream lists the sidecar alongside the studio + media containers, and the UI’s instances list renders it.
Networking
Section titled “Networking”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:
docker logs my-stream-connector-1 -fThe web UI’s logs view targets media/studio only — sidecar logs are docker-side for now.
Available environment variables
Section titled “Available environment variables”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.
Caveats
Section titled “Caveats”- 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-ctlonly checks the file exists —docker composedoes 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 anorsk-ctlvalidation message. - Image pulling. Pre-pull / rebuild your sidecar image before launch;
norsk-ctldoesn’t preflight sidecar images the way it does for the template’s own images. - Removed instances.
norsk-ctl instance deleteissuesdocker compose downagainst 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.