Skip to content

Security

The shape of a norsk-ctl deployment, security-wise: one public-facing TLS proxy, one local-only daemon API, and per-instance ingest ports that bind directly to the host. This page walks each surface and the cert sources you’ll pick between.

SurfaceDefault exposureHardening
Proxy front door (:443)PublicTLS-mandatory; HTTP Basic Auth or OAuth2; HTTP/2 + TLSv1.3 only
HTTP → HTTPS redirect (:80)Public unless --no-http-redirectDrops anything that isn’t a redirect or certbot HTTP-01 challenge
Daemon API (:8333)Loopback onlyFirewall it. Do not expose. The CLI and the MCP stdio bridge live on the same host
Studio + Media internal portsBridge-internal (docker); media on the host network in hybridNot advertised externally; Studio routed by container name on norsk-net
Ingest ports (SRT, RTMP, …)Public — published per-instanceEach pipeline decides; open only the ports your instances actually need

The insecure-HTTP mode was removed in #280. Every install picks a cert source at norsk-ctl init time (the interactive wizard offers all four; the installer flags map straight through).

SourceWhen to pick itWhat it gives you
mkcertLocal development on your laptopAuto-installs the mkcert root CA into your system trust store. Browsers on the same machine trust the resulting cert without warning. Local dev only — anything else won’t trust the CA
self-signedRemote box with no DNS name (cloud VM, on-prem IP-only)openssl mints a cert whose SAN covers the configured publicHost / --ip. Browsers show a one-time warning, then it’s real TLS
userYou have your own cert and key (corporate CA, mkcert-on-laptop scp’d over)Pass --cert-path and --key-path. norsk-ctl reads them at boot — renewal is on you
certbotYou have a public DNS name pointing at the boxAuto-issues a Let’s Encrypt cert via certbot’s HTTP-01 challenge on port 80. Renews on the cert’s normal cron

See Server install — overview for the decision flowchart, and Reverse Proxy for the cipher details.

certSource lives in config.yaml after init and influences the daemon’s renewal behavior for the sources it manages.

Two paths:

  • HTTP Basic Auth (default). Users live in nginx’s htpasswd file, managed via norsk-ctl user set/delete. Changes hot-reload nginx — no dropped connections.
  • OAuth2 via oauth2-proxy. Enabled at init by passing OAuth2 client credentials. Unauthenticated browsers are redirected through the IdP first.

The default admin user is whatever you set at install time. Rotate with norsk-ctl user set <name>; pass NORSK_ADMIN_PASSWORD in the environment to keep passwords off the command line and out of shell history.

:8333 is intentionally unauthenticated. The CLI, the web UI (via the proxy), and the local MCP stdio bridge all live on the same host. Do not expose :8333 to the public internet — at the cloud firewall, restrict it to localhost or block it entirely from the inbound rules.

The /mcp endpoint is special-cased: the nginx proxy will only forward /mcp requests originating on the loopback interface, so the local stdio bridge works but external traffic to https://<host>/mcp is blocked.

The license is per product: it’s supplied at registration time (norsk-ctl product add --license-file <path>) and stored on the product registration — there is no daemon-global license in config.yaml. The referenced file is mounted into the media container at launch. Treat it like any other credential — file permissions, backups, and rotation are on you. ~/.norsk-ctl/ is the conventional location.

For marketplace-licensed products (product add --marketplace-provider <aws|gcp>), the provider’s metering applies — no license file on disk.

CredentialWhereNotes
Proxy users (htpasswd)nginx htpasswd file under the proxy’s working dirHot-reloaded on user set/delete. Bcrypt-hashed
OAuth2 client secretconfig.yamlFile perms matter — chmod 600
TLS private keykeyPathFile perms matter
Norsk license fileproduct registration (product add --license-file)File perms matter
Instance / launch state~/.norsk-ctl/norsk-ctl.dbSQLite; daemon-managed
  • Get a DNS name. Real TLS via certbot is the cleanest user experience and avoids per-device trust workflows.
  • Restrict :8333. Even on a single-tenant VM, an inbound rule that allows only loopback removes a whole class of mistakes.
  • Use OAuth2 over basic auth if you have an IdP. Basic auth is fine for a small ops team, but OAuth2 inherits your existing user lifecycle.
  • Rotate the admin password. Set a strong one at install, change it with norsk-ctl user set <admin> periodically.
  • Backup ~/.norsk-ctl/. Both the config and the state DB. Without it, instance metadata and launch configs are lost. See Backup & Upgrade.
  • Pin image versions. Studio/Media versions come from the product template’s compose pins (with a per-launch image override available in the launch form). Pinned versions give you reproducibility.