Automated install
For unattended provisioning — CI, Ansible/Terraform, cloud-init — the --server
installer runs with no prompts. Everything the interactive install
asks for becomes a flag or an environment variable.
What you need
Section titled “What you need”- Root or passwordless
sudoon the target box (Ubuntu 22.04 / 24.04 / 26.04 LTS, Debian 12, or Oracle Linux 9). - A license file already on the box (e.g.
scp’d to/tmp/license.json). It must be the V2 format — a signed JSON envelope naming the products it entitles. Older V1 licenses are no longer accepted and must be reissued; contact Norsk support for a replacement. The installer checks the format during preflight, before it changes anything on the box, so a V1 file aborts the run up front instead of failing at the final registration step. - An admin password, ≥8 characters with at least one digit, from your secrets
manager — passed as
NORSK_ADMIN_PASSWORDso it never lands in a flag or your shell history.
Install norsk-ctl, unattended
Section titled “Install norsk-ctl, unattended”export NORSK_ADMIN_PASSWORD="$(vault read -field=pw secret/norsk)" # or your secrets store
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install.sh \ | sudo --preserve-env=NORSK_ADMIN_PASSWORD bash -s -- \ --server --license /tmp/license.json --ip auto --yes--yesskips the confirmation prompt — required non-interactively; without it the installer aborts for lack of a TTY.--ip autoputs the box’s detected public IP in the self-signed cert; use--public-host <name>for an explicit hostname, or--cert-source certbot --domain … --cert-email …for a trusted cert.--print(in place of--yes) prints the plan and exits without touching the box — a dry run your pipeline can diff.NORSK_ADMIN_PASSWORDis validated (≥8 chars, ≥1 digit); a weak value aborts before any changes are made.
Full flag list: Install overview and the Install script reference. Or ask
either script — --help works piped, so it needs no download:
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install.sh | bash -s -- --helpThen register a product
Section titled “Then register a product”install.sh --server leaves the daemon running but with no product registered —
register Studio to get something to launch. See
Register a product for the exact
product add --image command (pinned image, license path).
One shot: install + Studio together
Section titled “One shot: install + Studio together”The per-product bootstrap collapses both steps into one line — install norsk-ctl and register Studio:
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install/studio.sh \ | sudo bash -s -- --license /tmp/license.json --admin-password "$ADMIN_PW" --public-host auto--public-host names the address clients reach the box on — it goes into the
TLS certificate’s SAN and prefixes every advertised instance URL. Pass the DNS
name explicitly when you have one; auto probes for the public IP, which is
right for a cloud box and wrong behind NAT (it reports the outbound address, not
the one clients use). Omit it entirely only for a localhost-only install.
Registration does not launch anything: the box is left with Studio registered
and nothing running. Add --launch-examples if you want the sample-workflow
instance started as part of the install.
With a trusted certificate
Section titled “With a trusted certificate”The bootstrap takes the same TLS flags as install.sh, so a box with a DNS name
can be installed, certificated and registered in one line:
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install/studio.sh \ | sudo --preserve-env=NORSK_ADMIN_PASSWORD bash -s -- \ --license /tmp/license.json \ --cert-source certbot --domain norsk.example.com --cert-email ops@example.comCertbot issues the certificate over an HTTP-01 challenge, so norsk.example.com
must already resolve to this box and port 80 must be free and reachable from the
internet. --domain doubles as --public-host — pass --public-host as well
only if clients reach the box under a different name than the certificate is
issued for. To install your own certificate instead, use --cert-source user --cert-path <pem> --key-path <pem>; the default, with neither flag, is a
self-signed certificate.
Ports, on a box that already serves something
Section titled “Ports, on a box that already serves something”Three host ports are involved: 443 for the proxy, 80 for its HTTP→HTTPS redirect, and 8333 for the daemon. All three are checked before anything is installed — the install stops and names the port and the process holding it, so a busy box doesn’t cost you a half-configured one. Both installers take the same flags:
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install/studio.sh \ | sudo bash -s -- --license /tmp/license.json --admin-password "$ADMIN_PW" \ --proxy-port 8443 --http-redirect-port 8080| Flag | Effect |
|---|---|
--proxy-port <port> | Host port the proxy binds (default 443) |
--http-redirect-port <port> | Move the HTTP→HTTPS redirect listener off 80 |
--no-http-redirect | Drop that listener entirely. Incompatible with certbot, which needs port 80 for HTTP-01 |
--external-port <port> | Port clients arrive on, when it isn’t the one we bind — see below |
To install anyway, over a port the check flags — you’re about to stop whatever
holds it — set NORSK_CTL_SKIP_PORT_CHECK=1.
Behind another reverse proxy
Section titled “Behind another reverse proxy”When something else fronts the box — publishing 443 for several services and forwarding one of them to us — the port we bind is no longer the port a browser connects to. Say both:
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install/studio.sh \ | sudo bash -s -- --license /tmp/license.json --admin-password "$ADMIN_PW" \ --proxy-port 8443 --external-port 443 --public-host studio.example.com--proxy-port is where we listen, so it’s what the fronting proxy forwards to.
--external-port is where clients arrive, so it’s what every advertised URL
names: the oauth2 sign-in redirect, and the base URL baked into each instance at
launch. Set only the first and sign-in bounces the browser at :8443, which the
fronting proxy doesn’t publish.
On the fronting proxy, forward to https://<box>:8443 preserving the Host
header, allow WebSocket upgrades, and disable response buffering — the UI uses
Server-Sent Events and the instance screens use WebSockets, both of which a
buffering proxy silently breaks. Our certificate is self-signed unless you
installed your own, so that hop needs verification disabled (nginx:
proxy_ssl_verify off) or a real certificate via --cert-source user.
Only a subdomain at the root works today (https://studio.example.com). A
path prefix (https://example.com/ctl) is not supported: the UI, the nginx
routes, the oauth2 callback and the per-instance URL prefixes are all rooted at
/.
Cloud marketplace
Section titled “Cloud marketplace”On a cloud image where the provider supplies the license, swap the license flag for
--marketplace-provider gcp (or aws) — the daemon reads the license from instance
metadata instead of a file. Building the marketplace image itself is a vendor step,
not covered here.