Architecture
norsk-ctl is a single Go-free binary. When it runs it puts three kinds of process on the host: the daemon itself, an nginx reverse proxy (in Docker mode), and a pair of Studio + Media containers for every instance you launch.
Process model
Section titled “Process model”- Daemon — the
norsk-ctlbinary running as a long-lived process. Hosts the HTTP API (port8333), the web UI (served from the same port), and orchestrates Docker for everything else. Users drive the CLI against this daemon. - Proxy container —
norsk-proxy, an nginx image on thenorsk-netDocker bridge. Terminates TLS (if configured), routes/api/…to the daemon on the host and/instances/<id>/…to the right Studio container. Not started inhostmode. - Studio + Media per instance —
norsk-studio-<id>(web canvas + gRPC client) andnorsk-media-<id>(the actual media engine). Two containers per instance, both onnorsk-netin Docker mode.
See Network Modes for how these pieces vary between docker, hybrid and host networking.
Network topology (Docker mode)
Section titled “Network topology (Docker mode)”Two traffic classes, and the distinction matters. Proxied traffic (browser requests and API calls) flows through nginx on the Docker bridge. Direct traffic (SRT/RTMP media ingest) bypasses nginx and binds straight from norsk-media to the host.
Request flow
Section titled “Request flow”- Browser → nginx — nginx publishes a single configurable port on the host (80, 443, or whatever you set at init). Internally it listens on
:9090. - nginx → backend — requests to
/api/are forwarded tohost.docker.internal:8333, where the daemon runs on the host. - nginx → studio — requests to
/instances/<id>/…are forwarded tonorsk-studio-<id>:8000onnorsk-net, matched by instance ID in the URL path. WebSocket upgrades are passed through. - Studio → media — Studio talks to its paired Media container over gRPC (
:6790) and HTTP (:8080) onnorsk-net. - Ingest → media — SRT, RTMP and other ingest ports are published directly from
norsk-mediato the host. They never touch nginx.
Port uniqueness
Section titled “Port uniqueness”Internal container ports (8000, 6790, 6791, 8080) are resolved by container name on norsk-net. Multiple instances can all listen on the same internal ports without conflict — Docker routes by name, not by port.
Ingest ports are different. They are published directly from norsk-media-<id> to the host, so two instances binding the same host port will clash. Ingest ports must be globally unique across all running instances.
Port reference
Section titled “Port reference”| Port | Container | Direction | Proxied? | Protocol | Unique across instances? | Notes |
|---|---|---|---|---|---|---|
| configurable (e.g. 80) | norsk-proxy | host → container :9090 | — | HTTP | N/A (single proxy) | Proxy listen port, maps to nginx internal :9090 |
| 8333 | host (daemon) | proxy → host | Yes | HTTP | N/A (single daemon) | API + web UI, reached via host.docker.internal |
| 8000 | norsk-studio-<id> | proxy → container | Yes | HTTP/WS | No — per-container | Studio UI, resolved by container name on norsk-net |
| 6790 | norsk-media-<id> | studio → media | No (internal) | gRPC | No — per-container | Media engine API |
| 6791 | norsk-media-<id> | container-internal | No (internal) | HTTP | No — per-container | Health check |
| 8080 | norsk-media-<id> | studio → media | No (internal) | HTTP | No — per-container | Media HTTP API |
| SRT/RTMP/… | norsk-media-<id> | host → container | No (direct) | UDP/TCP | Yes — must be unique | Ingest ports bound directly to host |
When TLS is enabled, nginx terminates it on the proxy port (typically 443). The proxy overlay adds:
ssl_certificate/ssl_certificate_keyvolume mounts- TLSv1.3 only, with post-quantum cipher group
X25519MLKEM768andTLS_AES_256_GCM_SHA384 - HTTP/2 enabled
Upstream connections (proxy → daemon, proxy → Studio) stay plain HTTP over norsk-net.