Skip to main content

Chart installation

Install the OpenBox chart onto a Kubernetes cluster you already run (EKS, AKS, GKE or self-managed). On Amazon EKS and buying through AWS Marketplace? Use AWS Marketplace instead — images come from AWS and there is no registry credential to manage.

Before you start​

  • Kubernetes 1.27 or later, with an ingress controller and a default StorageClass — see System requirements
  • Helm 3.14 or later
  • A GitHub credential with read:packages on ghcr.io/openbox-ai — the chart's images are private
  • Your OpenBox license bundle (license.jwt, report-signing.key) and tenant ID
  • A DNS domain for five hostnames: openbox-eks, openbox-api, openbox-core, identity, opa

1. Namespace, registry and license secrets​

kubectl create namespace openbox

# Pull secret for the private ghcr.io images
kubectl -n openbox create secret docker-registry ghcr-openbox \
--docker-server=ghcr.io \
--docker-username=YOUR_GITHUB_USER \
--docker-password=YOUR_READ_PACKAGES_TOKEN

# License — from your license bundle
kubectl -n openbox create secret generic openbox-license \
--from-file=token=./license.jwt \
--from-file=report-signing-key=./report-signing.key
Create the license secret first

If openbox-license is missing, the pre-install license check waits forever for it and helm install hangs with no error until it times out.

2. Values file​

Save as my-values.yaml, replacing YOUR_DOMAIN and YOUR_TENANT_ID:

global:
imagePullSecrets:
- name: ghcr-openbox
ingress:
type: nginx # nginx | traefik | istio | none
className: nginx
domain: YOUR_DOMAIN
license:
expectedTenantId: YOUR_TENANT_ID
# Set true unless you have your own Google reCAPTCHA keys —
# otherwise nobody can sign in.
recaptcha:
disabled: true
# Optional: create the first organization and administrator at install.
# The organization ID is the email's domain; public providers are rejected.
seedOrg:
enabled: true
adminEmail: you@your-company.com

# Public addresses the console and API are served on.
openbox-fe:
extraEnv:
- { name: VITE_API_URL, value: "https://openbox-api.YOUR_DOMAIN" }
- { name: VITE_CORE_API_URL, value: "https://openbox-core.YOUR_DOMAIN" }
- { name: VITE_WS_URL, value: "https://openbox-api.YOUR_DOMAIN" }
- { name: VITE_KEYCLOAK_BASE_URL, value: "https://identity.YOUR_DOMAIN" }
- { name: VITE_KEYCLOAK_CLIENT_ID, value: "openbox" }
- { name: VITE_KEYCLOAK_SHARED_REALM, value: "openbox" }
openbox-backend:
secret:
stringData:
KEYCLOAK_BASE_URL: "https://identity.YOUR_DOMAIN"
FRONTEND_URL: "https://openbox-eks.YOUR_DOMAIN"
ALLOWED_ORIGINS: "https://openbox-eks.YOUR_DOMAIN"
KEYCLOAK_CLIENT_ROOT_URL: "https://openbox-eks.YOUR_DOMAIN/*"
KEYCLOAK_CLIENT_HOME_URL: "https://openbox-eks.YOUR_DOMAIN/"
KEYCLOAK_CLIENT_REDIRECT_URIS: "https://openbox-eks.YOUR_DOMAIN/*"
KEYCLOAK_CLIENT_WEB_ORIGINS: "https://openbox-eks.YOUR_DOMAIN"
KEYCLOAK_CLIENT_ADMIN_URL: "https://openbox-eks.YOUR_DOMAIN/*"
KEYCLOAK_CLIENT_POST_LOGOUT_REDIRECT_URIS: "https://openbox-eks.YOUR_DOMAIN/*"

Without the public-address block, the console cannot reach the API and Keycloak rejects the login redirect. The redirect and origin addresses are written into an organization when it is created, so get them right on the first install.

No default StorageClass? Add, per volume:

postgresql:
primary:
persistence:
storageClass: YOUR_CLASS
openbox-core:
redis:
storageClass: YOUR_CLASS
identity-service:
persistence:
storageClassName: YOUR_CLASS # note: storageClassName here

No GPU node? Add llamafirewall: { enabled: false }.

3. Install​

helm install openbox oci://ghcr.io/openbox-ai/charts/openbox \
--version 0.1.7 \
-n openbox \
-f my-values.yaml \
--timeout 15m

Install without --wait, as the CDK deployment does: with --wait, Helm holds the post-install Keycloak bootstrap until every workload is Ready, which can outlast the timeout on a first install. Watch convergence instead:

kubectl -n openbox get pods -w

Allow about 10 minutes. Pods that depend on the database schema or the workflow engine show Init until it is ready (chart 0.1.6 and later); one Temporal pod may restart once. Repeated restarts mean a real fault.

With seedOrg enabled, the administrator's generated password is:

kubectl -n openbox get secret openbox-seed-admin -o jsonpath='{.data.password}' | base64 -d; echo

Then create DNS records for the five hostnames pointing at your ingress load balancer, and sign in at https://openbox-eks.YOUR_DOMAIN.

Governance policies need an S3 bucket

The backend publishes policies and behavior rules as one bundle to S3, and OPA reads it from there. Until you set global.policyBundle (bucket, region, and two IRSA roles), saving a policy or behavior rule fails and OPA has no policy, so every agent action is allowed. You can add it at install or later with helm upgrade --reset-then-reuse-values; the steps and IAM permissions are in AWS Marketplace → Install → Governance policies and apply to this chart unchanged. On the GHCR chart up to 0.1.7, the backend signs S3 with static keys only (IRSA support for the backend arrives with the next backend release).

Upgrade​

helm upgrade openbox oci://ghcr.io/openbox-ai/charts/openbox \
--version NEW_VERSION -n openbox \
--reset-then-reuse-values -f my-values.yaml

Use --reset-then-reuse-values, not --reuse-values: the latter keeps the old chart's defaults and silently ignores settings a new version introduces.

The license check also runs before every upgrade, so openbox-license must still exist.

Rollback​

helm history openbox -n openbox
helm rollback openbox <revision> -n openbox

Rollback restores Kubernetes resources but not the database schema. If the upgrade ran migrations, plan the rollback with whoever owns the data.

Uninstall​

helm uninstall openbox -n openbox

Generated secrets (openbox-gen-*, openbox-seed-admin) and PersistentVolumeClaims are kept on purpose, so a reinstall over the same volumes still has matching credentials. To remove all data, delete them together:

kubectl -n openbox delete pvc --all
kubectl -n openbox get secret -o name | grep -E 'openbox-gen-|openbox-seed-admin' | xargs kubectl -n openbox delete
Never delete one without the other

Deleting the secrets but keeping the volumes leaves the database with passwords that no longer match: PostgreSQL crash-loops, and the only recovery is deleting the volume.

Preview without applying​

helm template openbox oci://ghcr.io/openbox-ai/charts/openbox \
--version 0.1.7 -n openbox -f my-values.yaml > preview.yaml

Values precedence (lowest → highest)​

  1. Chart values.yaml (built-in defaults)
  2. Sub-chart values.yaml (per sub-chart defaults)
  3. -f my-values.yaml
  4. --set key=value
  5. --set-file key=path (multi-line values)

Lists are replaced, not merged: if you set openbox-fe.extraEnv in more than one place, only the last one survives. Keep the public-address entries and any of your own in one list.

Values reference​

Every top-level key is documented at Values reference.