# Install with a License

Install an Omnia licence key so an Enterprise install moves from dev mode to licensed. For what the three states mean and what a licence gates, see [Licensing & Features](/explanation/platform/licensing/).

## Prerequisites

- A Kubernetes cluster at version 1.26 or later and Helm 3.
- An Omnia licence key. Request one at [sales@altairalabs.ai](mailto:sales@altairalabs.ai) or start a [free trial](https://omnia.altairalabs.ai/trial).

## Install with the key in Helm values

1. Install the `omnia-crds` release first. The app chart refuses to install without it, and `helm upgrade` of the app chart never updates CRDs.

   ```bash
   helm install omnia-crds oci://ghcr.io/altairalabs/charts/omnia-crds \
     --devel \
     --namespace omnia-system --create-namespace
   ```

   This chart installs the Enterprise kinds by default. Pass `--set enterprise.enabled=false` to leave them out.

2. Install the app chart with Enterprise on and the key set. The chart creates the `arena-license` Secret from `license.key`.

   ```bash
   helm install omnia oci://ghcr.io/altairalabs/charts/omnia \
     --devel \
     --namespace omnia-system \
     --set dashboard.auth.mode=builtin \
     --set enterprise.enabled=true \
     --set license.key="<licence-jwt>" \
     -f values.yaml
   ```

   `values.yaml` names the Redis and the database `builtin` mode needs (`redis.default` and `managementApi.database.existingSecret`), as [Configure builtin authentication](/how-to/security/configure-dashboard-auth-builtin/) shows. The chart fails to render without them.

## Install with an existing Secret

Use this path when you manage the Secret outside Helm, for example with GitOps.

1. Create the Secret. The name must be `arena-license`, it must be in the namespace Omnia is installed into, and the JWT must be under the `license` key. The operator looks the Secret up by that fixed name.

   ```bash
   kubectl create secret generic arena-license \
     --namespace omnia-system \
     --from-literal=license="<licence-jwt>"
   ```

2. Install the `omnia-crds` release as in the previous section, then install the app chart. Set `license.existingSecret` to any non-empty value to stop the chart creating its own Secret. It does not rename the Secret the operator reads.

   ```yaml
   # values.yaml
   enterprise:
     enabled: true
   license:
     existingSecret: "arena-license"
   ```

   ```bash
   helm install omnia oci://ghcr.io/altairalabs/charts/omnia \
     --devel \
     --namespace omnia-system \
     --set dashboard.auth.mode=builtin \
     -f values.yaml
   ```

3. If a tool outside the chart applies the Secret and you set neither `license.key` nor `license.existingSecret`, set `license.externallyManaged: true`. Otherwise the chart derives dev mode and the services log the dev-mode banner despite the valid licence.

## Upload through the dashboard

1. Sign in as a user with the `admin` role, which holds `settings:edit`.
2. Open **Settings**, then the **License** tab.
3. Select **Upload License**.
4. Drop the file on the drop zone, or select **Browse Files**. The file holds the JWT and can be `.jwt`, `.license`, `.txt` or `.pem`.

management-api writes the JWT into the `arena-license` Secret in the namespace Omnia is installed in. A confirmation or error appears under the button.

## From a marketplace purchase

An install connected to the Altaira Labs control plane (`controlPlane.url`) needs no key. After it registers, the operator fetches the licence for the purchase and writes it into the `arena-license` Secret, the same Secret the other methods use. It checks the licence's signature first, and never replaces the installed licence with one issued earlier. If the control plane is unreachable, or sends a licence that does not verify, the installed licence stays in force. Renewals arrive on the operator's daily heartbeat: from 30 days before the installed licence expires, each heartbeat asks the control plane for its successor.

Leave `license.key` unset on a connected install. The chart refuses it alongside `controlPlane.url`, because every `helm upgrade` would write the key back over the licence the control plane issued.

The outcome is an event on the `omnia-installation` ConfigMap:

```bash
kubectl get events -n omnia-system \
  --field-selector involvedObject.name=omnia-installation
```

`EntitlementInstalled` names the licence and its expiry. `EntitlementRejected` says why a licence was refused.

## Apply the licence

The licence validator caches the result for five minutes, so a new or changed key can take that long to show. To apply it at once, restart the Omnia Deployments:

```bash
kubectl rollout restart deployment -n omnia-system \
  -l app.kubernetes.io/instance=omnia
```

Services that resolve the licence once at startup, such as workspace memory-api and privacy-api, need their own restart.

## Update the licence

With `license.key`, upgrade the app chart with the new key. `--reuse-values` keeps every other value.

```bash
helm upgrade omnia oci://ghcr.io/altairalabs/charts/omnia \
  --devel \
  --namespace omnia-system \
  --reuse-values \
  --set license.key="<new-licence-jwt>"
```

With an existing Secret, replace its contents:

```bash
kubectl create secret generic arena-license \
  --namespace omnia-system \
  --from-literal=license="<new-licence-jwt>" \
  --dry-run=client -o yaml | kubectl apply -f -
```

Then [apply the licence](#apply-the-licence).

## Back up the licence Secret

Without the `arena-license` Secret the install runs in dev mode and logs the banner while every feature still works. Save the token to a file kept with your other recovery material:

```bash
kubectl get secret arena-license -n omnia-system \
  -o jsonpath='{.data.license}' | base64 -d > omnia-license.jwt
```

Re-applying the saved JWT is the whole of recovery.

## Verify

1. Open the dashboard and check the licence tab.

   ```bash
   kubectl port-forward svc/omnia-dashboard 3000:3000 -n omnia-system
   ```

   Open `http://localhost:3000/settings`. The **License** tab shows **Tier** `Enterprise` and a status pill of **Active**. Dev mode shows the same tier and status, so check that **Customer** shows your organisation and not `Development Mode`.

2. Confirm the services log no licence banner. A licensed install logs none at startup:

   ```bash
   kubectl logs -l app.kubernetes.io/name=omnia -n omnia-system --tail=-1 \
     | grep -iE "development license|without a valid license"
   ```

   No output means no service is running in dev mode or on an invalid licence.

## Troubleshooting

### The licence is not recognised

Confirm the Secret exists and holds a `license` key:

```bash
kubectl describe secret arena-license -n omnia-system
```

The output lists a `license` entry with a byte count. If the Secret is correct, look for validation errors in the logs:

```bash
kubectl logs -l app.kubernetes.io/name=omnia -n omnia-system --tail=-1 \
  | grep -i "license"
```

### Enterprise CRDs are missing

`omnia-crds` installs the Enterprise kinds unless the release was installed with `enterprise.enabled=false`. Upgrade the release with the value on:

```bash
helm upgrade omnia-crds oci://ghcr.io/altairalabs/charts/omnia-crds \
  --version <version> -n omnia-system \
  --set enterprise.enabled=true
```

If the upgrade fails with `invalid ownership metadata`, the CRDs have no Helm ownership. Hand them to the release, then upgrade again:

```bash
hack/adopt-crds.sh --context <kube-context> --release-namespace omnia-system
```

Then enable Enterprise on the app chart:

```bash
helm upgrade omnia oci://ghcr.io/altairalabs/charts/omnia --devel \
  --namespace omnia-system \
  --reuse-values \
  --set enterprise.enabled=true
```

### The licence has expired

Every feature keeps working. Each service logs a startup reminder and the dashboard shows an expiry advisory. Contact support to renew, then [update the licence](#update-the-licence).

### Activation failed

Activation is optional and never disables a feature; a failure records a Kubernetes warning event. To make it succeed:

1. Check the cluster can reach `https://license.altairalabs.ai`.
2. If the warning event says the licence is over its activation limit, contact [support](mailto:sales@altairalabs.ai) to free a slot held by a cluster you have retired.

Air-gapped clusters need no offline procedure. Validation needs no network.

## Related pages

- [Licensing & Features](/explanation/platform/licensing/) explains the three states, validation and activation.
- [Configure Arena S3 Storage](/how-to/evaluation/configure-arena-s3-storage/) sets up artifact storage (Enterprise).
- [Setup Scheduled Jobs](/how-to/evaluation/setup-arena-scheduled-jobs/) configures job scheduling (Enterprise).