Skip to content

Server install walkthrough (Oracle Linux)

A real, start-to-finish run of the one-shot --server installer on a fresh box — every command and its actual output, annotated. By the end you’ll have the norsk-ctl daemon running under systemd behind a TLS proxy, ready to sign into.

Throughout: command blocks are highlighted and have a copy button — those are what you type. Output blocks are plain and have no copy button — that’s what you should see back.

You’ll need:

  • A fresh Oracle Linux 9 box with sudo and SSH access. Aim for 8 vCPU / 16 GB RAM / 60 GB+ disk.
  • Your Norsk license file (license.json) on your laptop — you’ll copy it across in step 1.
  • A password for the admin web user — pick a strong one. You’ll pass it via an environment variable so it never lands in your shell history.
  • The address clients will use to reach the box — its public IP or DNS name. Below we write <host>; substitute your box’s address.

The install takes ~3–5 minutes, mostly installing Docker. It does not pull the large Studio/Media images by default — add --pull-images if you want them fetched up front.

From your laptop:

Terminal window
scp license.json opc@<host>:/tmp/license.json

SSH into the box, download the installer, set your admin password, and run it in --server mode. The full source of install.sh is inlined in the reference if you want to read it before running — see Reference: the installer. The flags:

  • --server — full daemon install: Docker (if missing), a norsk service user, a systemd unit, and TLS.
  • --license — the license file you just copied.
  • --public-host — the address clients use; it goes into the self-signed certificate. (Use --ip auto to auto-detect a public IP instead.)

The installer prints its plan and asks you to confirm before touching the box. Type y at the [y/N]: prompt to proceed — pass --yes to skip it in automation.

Terminal window
curl -fsSL https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl/install.sh -o install.sh
read -rs -p 'Admin password: ' NORSK_ADMIN_PASSWORD; echo
export NORSK_ADMIN_PASSWORD
bash install.sh --server --license /tmp/license.json --public-host <host>
preflight — server capability check:
warn CPU cores 4 vCPU (8 vCPU recommended)
warn RAM 4 GB (16 GB recommended)
warn free disk 56 GB (100 GB recommended)
ok cgroup unified hierarchy
ok arch arm64
norsk-ctl install plan — mode: server, platform: linux-<arch>
public host <host>
cert source self-signed
licence /tmp/license.json
server (Ubuntu LTS, Debian, or Oracle Linux; uses sudo per step, not run as root):
1. If 'docker compose' is missing, install Docker Engine + the Compose plugin
from Docker's official package repository.
2. Create the 'norsk' service user and FHS dirs under /etc, /var/lib, /var/log.
3. Install the CLI to /opt/norsk-ctl/bin with a /usr/local/bin/norsk-ctl symlink.
4. Apply sysctl tuning and write a systemd unit (norsk-ctl.service).
5. Configure the daemon (via 'norsk-ctl init', TLS: self-signed by default),
then enable + start the norsk-ctl systemd unit so it comes up on boot.
Proceed — install Docker (if needed), a systemd service, and start norsk-ctl? (will use sudo for each system step)
[y/N]:
==> installing Docker Engine + Compose plugin
==> added <user> to the docker and norsk groups (open a new shell, or run 'newgrp norsk' — one call activates both)
==> installed norsk-ctl <version>
==> license staged at /etc/norsk-ctl/licenses/license.json — register products with 'norsk-ctl product add --license-file /etc/norsk-ctl/licenses/license.json'
Proxy user "admin" created
Config written to /etc/norsk-ctl/config.yaml (TLS enabled)
Public URL (from --public-host): https://<host>
Created symlink /etc/systemd/system/multi-user.target.wants/norsk-ctl.service → /etc/systemd/system/norsk-ctl.service.
════════════════════════════════════════════════════════════════
==> install complete
UI: https://<host> (sign in as admin)
Service: systemctl status norsk-ctl
Logs: journalctl -u norsk-ctl -f
Shell: source /etc/profile.d/norsk-ctl.sh (or open a new shell)
Files:
Config /etc/norsk-ctl config.yaml, licenses/, certs/
State /var/lib/norsk-ctl database, product registry, templates, instances, proxy
Logs /var/log/norsk-ctl per-instance and proxy logs
Binary /opt/norsk-ctl/bin versioned; /usr/local/bin/norsk-ctl symlinks to it
Back up /etc/norsk-ctl and /var/lib/norsk-ctl to capture config + state.
════════════════════════════════════════════════════════════════

read -rs reads the password into the variable without echoing it to the terminal and without it ever appearing in your shell history. In a longer-running deployment you’d typically pull this from a secrets manager (Vault, AWS Secrets Manager, etc.) into the same env var instead — and the proxy auth layer itself can also be replaced by an SSO integration as part of a production setup.

You don’t need to run the installer with sudo yourself — install.sh runs as you and escalates via sudo only for the system-mutation steps (apt-get, writes under /etc and /opt, systemctl). You’ll be prompted once for your sudo password after you confirm the plan; sudo caches the credential for the rest of the run.

That last ==> UI: line is your finish line. Reading the output top to bottom: the installer printed its plan and you confirmed with y; Docker was installed and enabled, the norsk service user and its directories were created, norsk-ctl init wrote /etc/norsk-ctl/config.yaml and minted a self-signed cert for <host>, and the norsk-ctl systemd service was enabled and started.

Before checking the daemon, here’s where install.sh put things. Knowing the layout makes troubleshooting later much easier.

Config: the rendered config.yaml and the licence install.sh copied in. For self-signed TLS, the cert and key sit alongside them in the certs/ subdirectory shown above (owned by the norsk service user).

Terminal window
ls -l /etc/norsk-ctl/
total 4
drwxr-xr-x. 2 norsk norsk 37 <timestamp> certs
-rw-r--r--. 1 norsk norsk 187 <timestamp> config.yaml
drwxr-x---. 2 norsk norsk 26 <timestamp> licenses

Binary: the versioned norsk-ctl binary lives here; /usr/local/bin/norsk-ctl is a symlink to it so upgrades are just a re-symlink.

Terminal window
ls -l /opt/norsk-ctl/bin/
total 108356
-rwxr-xr-x. 1 norsk norsk 110954816 <timestamp> norsk-ctl-<version>

Systemd unit: managed by systemctl {start,stop,status} norsk-ctl.

Terminal window
ls -l /etc/systemd/system/norsk-ctl.service
-rw-r--r--. 1 root root 568 <timestamp> /etc/systemd/system/norsk-ctl.service
Terminal window
norsk-ctl --version
<version>
Terminal window
systemctl is-active docker norsk-ctl.service
active
active

Two active lines mean Docker and the daemon are both up.

If you plan to drive the CLI from this same shell (e.g. norsk-ctl user set <name>), source the env file once so it picks up the production paths the installer just wrote:

Terminal window
source /etc/profile.d/norsk-ctl.sh

A fresh login (or ssh session opened after the install) does this for you. Without it the CLI looks under ~/.norsk-ctl/ for the proxy secret and the daemon redirects with Redirected to proxy — stale or missing proxy secret.

Open https://<host> and sign in as admin with the password you set. Your browser shows a one-time “not trusted” warning — that’s the self-signed certificate. It’s real TLS, so it’s safe to continue.

norsk-ctl is the control plane — a fresh install has no product registered, so there’s nothing to launch yet. Register the products your license entitles; the daemon reads the license, pulls each product’s image, reads its manifest, and imports the default (examples) product template:

Terminal window
norsk-ctl product add --license-file /etc/norsk-ctl/licenses/license.json

The image comes from the license (add --product <name> to register just one, or --tag <tag> to pin a version). The license path must be readable by the norsk service user — install.sh --license stages your file under /etc/norsk-ctl/licenses/, keeping its filename (here license.json, the name it was copied across as in step 1). See Products & Templates for the full product → template → instance model.

Back in the dashboard, launch a Studio instance from the registered product template — or from the CLI with norsk-ctl template list then norsk-ctl instance launch-template.

  • Ports & host detection — what to open in the firewall, and how to change the proxy port.
  • Pre-pull the proxy images with norsk-ctl proxy pull (or pass --pull-images at install); a product’s images pull on first launch, or ahead of time with norsk-ctl product pull <product> once it’s registered.
  • Stuck? journalctl -u norsk-ctl -f tails the daemon logs; the Troubleshooting page has the common gotchas.