Skip to content

Reverse Proxy

In both network modes, norsk-ctl runs an nginx reverse proxy (norsk-proxy) as the single entry point for browser traffic. It terminates TLS, enforces authentication, and routes requests to the right instance’s containers by matching the instance ID in the URL path. Every instance’s UI is fronted by the proxy, whatever product it comes from; the modes differ only in how the proxy reaches an instance’s media container (over the bridge in docker, via the host in hybrid).

  • Single external port — all instances reachable through one URL (default :443) instead of one port per instance
  • Path-based routing — each instance lives at /instance/<id>/…
  • Authentication — HTTP Basic Auth (htpasswd) by default; OAuth2 (via oauth2-proxy) for IdP-backed deployments
  • TLS termination — HTTPS at the edge, plain HTTP to upstreams on norsk-net
  • Zero-downtime reload — adding instances or users doesn’t drop live connections

See Architecture for a diagram of how proxied and direct (ingest) traffic flow together.

Each running instance surfaces several paths under /instance/<id>/:

PathUpstreamPurpose
/instance/<id>/the template’s runtime-screen service (Studio: <id>-studio-1:8000)Instance runtime UI
/instance/<id>/studio/<id>-studio-1:8000Studio UI (with WebSocket upgrade)
/instance/<id>/media/<id>-media-1:8080Media HTTP API
/instance/<id>/visualiser/<id>-media-1 (visualiser port)Pipeline visualiser
/instance/<id>/uvis/<id>-media-1 (visualiser port)Unified visualiser (WebSocket)
/instance/<id>/status<id>-media-1 (visualiser port)Instance status endpoint
/products/<name>/host.docker.internal:8333 (daemon forwards to the product’s backend)Registered product’s config UI
/api/host.docker.internal:8333norsk-ctl daemon API
/mcphost.docker.internal:8333MCP HTTP endpoint (loopback bypass for local stdio bridges)
/host.docker.internal:8333norsk-ctl web UI

Default proxy port is 443 (HTTPS) across all network modes. Port 80 is bound for an HTTP→HTTPS redirect plus certbot HTTP-01 validation; pass --no-http-redirect to skip (then certbot is no longer available — it needs port 80). Override the HTTPS port with --proxy-port N at install / init, or proxyPort: in config.yaml. See Ports for the full picture.

The legacy 9443 / 9080 docker-mode defaults are gone — TLS is mandatory and 443 is the unified default.

Terminal window
norsk-ctl proxy start # Start the nginx container and generate config from running instances
norsk-ctl proxy stop # Stop and remove the proxy container
norsk-ctl proxy reload # Regenerate config and reload nginx (zero-downtime)
norsk-ctl proxy status # Show proxy container status and active upstreams
norsk-ctl proxy pull # Pre-pull the nginx (and oauth2-proxy, if applicable) images
norsk-ctl proxy logs # View access or error logs (--type access|error, -n, -f)

norsk-ctl init starts the proxy automatically in docker and hybrid modes. Subsequent launches trigger a proxy reload, so you rarely run these commands by hand.

Users live in an nginx htpasswd file managed via the user subcommands.

Terminal window
# Add or update (prompts for password, or pipe via stdin)
norsk-ctl user set alice
# Remove a user
norsk-ctl user delete alice

Changes take effect immediately — the daemon writes the htpasswd file and tells nginx to reload without dropping connections. No manual proxy reload needed.

For deployments fronted by an identity provider (Google, Okta, etc.), norsk-ctl can run oauth2-proxy alongside nginx. Enable at init by passing OAuth2 credentials — the proxy then redirects unauthenticated users through the IdP before forwarding to the upstream.

/mcp is special-cased: it bypasses proxy auth when the request originates from the loopback interface. That lets norsk-ctl mcp (the local stdio bridge) talk to the daemon’s HTTP MCP endpoint without juggling auth credentials. External requests to /mcp over the public proxy URL are blocked.

TLS is mandatory; the insecure HTTP mode was removed. nginx adds an HTTPS server block listening on proxyPort (default 443) with:

  • TLSv1.3 only
  • Post-quantum cipher group X25519MLKEM768 + TLS_AES_256_GCM_SHA384
  • HTTP/2 enabled

Plain HTTP requests to port 80 are redirected to HTTPS (unless --no-http-redirect was passed at install).

Certificate provenance is tracked via certSource in config.yamlmkcert for local dev, self-signed for IP-only servers, user for a bring-your-own cert, certbot for auto-renewed Let’s Encrypt. See Security for the picker guide.

Terminal window
# Tail access log
norsk-ctl proxy logs --type access -f
# Last 200 lines of the error log
norsk-ctl proxy logs --type error -n 200

Both also appear in the Logs → Proxy view in the web UI.