Licensed to be used in conjunction with basebox, only.
basebox - Using Helm Charts
Install basebox from the OCI Helm registry with one command.
Use this page for real domains, cert-manager based TLS, or customer-managed TLS secrets.
Current stable release
The basebox.ai chart version is 0.3.32 and deploys
basebox 1.8.8 components.
To deploy optional in-cluster connector services, see Deploy MCP Connectors with Helm.
If basebox will use an LLM on a separate GPU server, read Deployment Topologies first. The basebox application cluster can be CPU-only when all GPU workloads are placed elsewhere or configured in CPU mode.
Looking for the shortest local install path?
If you want a single-node basebox.local evaluation install with local/self-managed TLS defaults, use Local Quick Start.
Prerequisites
- Kubernetes cluster already prepared
kubectlandhelminstalled on your workstation- CloudNativePG operator installed on the cluster
- ingress controller installed on the cluster
- NVIDIA GPU support installed on nodes that run inference or GPU-mode RAG services; it is not required on a CPU-only application cluster using external inference
- DNS for your public hostname already points to the ingress IP
- cert-manager installed and a
ClusterIssueravailable if you useglobal.tls.mode=cert-manager
Registry Credentials
The OCI chart is published at oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai.
If OCI pull or registry login requires credentials, use username pacman with this token:
TLS Modes
The chart behavior is controlled by global.tls.mode.
local
- local/self-managed TLS
- AISRV uses JWKS file mode
- intended for local evaluation and internal installs
cert-manager
- cert-manager manages the ingress TLS secret
- AISRV uses normal JWKS URL mode
- recommended for public domains
existing-secret
- you provide the ingress TLS secret yourself
- AISRV uses normal JWKS URL mode
- use this when you already manage TLS
The hostname itself is not the differentiator, e.g. basebox.internal can use local or existing-secret. What matters is the TLS trust model.
Step 1: Set Kubeconfig
Step 2: Optional OCI Registry Login
If anonymous OCI pull works in your environment, this step is optional.
Step 3: Choose a TLS Configuration
Choose exactly one of the following options. Do not run both Helm commands.
helm upgrade --install installs basebox when the release does not exist and
upgrades the existing release when it does.
Option A: Use cert-manager
Use this option when cert-manager is installed and the cluster has a suitable
ClusterIssuer. cert-manager creates and renews the Kubernetes TLS Secret named
by global.tls.secretName.
helm upgrade --install basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
--version 0.3.32 \
-n basebox \
--create-namespace \
--wait \
--timeout 120m \
--set global.domain=kubetest.bbox-dev.de \
--set global.tls.mode=cert-manager \
--set global.tls.clusterIssuer=letsencrypt-prod \
--set global.tls.secretName=kubetest-bbox-dev-de-tls \
--set quickstart.adminEmail=admin@kubetest.bbox-dev.de
What this does:
- installs all basebox services and databases
- creates bootstrap secrets automatically
- configures ingress for
kubetest.bbox-dev.de - asks cert-manager to issue the TLS certificate
- configures OIDC for the same external hostname
Option B: Use an Existing TLS Secret
Use this option when you already have the certificate and private key.
A Kubernetes TLS Secret is a Secret of type kubernetes.io/tls. It contains the
certificate in tls.crt and its private key in tls.key. The Secret must be in
the same namespace as basebox, and its name must match
global.tls.secretName.
For example, create the basebox namespace and a Secret named customer-tls:
kubectl create namespace basebox --dry-run=client -o yaml | kubectl apply -f -
kubectl -n basebox create secret tls customer-tls \
--cert=<PATH_TO_TLS_CERTIFICATE> \
--key=<PATH_TO_TLS_PRIVATE_KEY>
Then install or upgrade basebox using that Secret:
helm upgrade --install basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
--version 0.3.32 \
-n basebox \
--create-namespace \
--wait \
--timeout 120m \
--set global.domain=basebox.customer.internal \
--set global.tls.mode=existing-secret \
--set global.tls.secretName=customer-tls \
--set quickstart.adminEmail=admin@basebox.customer.internal
Requirements for this mode:
- secret
customer-tlsalready exists in namespacebasebox - Secret type is
kubernetes.io/tlsand it containstls.crtandtls.key - certificate is valid for
global.domain
Step 4: Verify the TLS Configuration
For either TLS mode, check that the ingress uses your configured hostname:
If you selected Option A (cert-manager), watch the certificate resources:
Expected:
- certificate resources move to ready state
If you selected Option B (existing-secret), verify the Secret type:
Expected:
In both modes, the ingress host must match global.domain.
k3s DNS Issues
If you are using k3s, please see this FAQ item to avoid DNS issues.
Step 5: Check Pods and Bootstrap Job
kubectl -n basebox get pods
kubectl -n basebox wait --for=condition=complete job/idp-keycloak-bootstrap --timeout=10m
Expected:
- service pods become
Running idp-keycloak-bootstrapcompletes successfully
Step 6: Get Login Credentials
Primary UI login:
kubectl -n basebox get secret basebox-admin-secret \
-o jsonpath='{.data.ADMIN_EMAIL}' | base64 -d && echo
kubectl -n basebox get secret basebox-admin-secret \
-o jsonpath='{.data.ADMIN_PASSWORD}' | base64 -d && echo
Keycloak admin password:
kubectl -n basebox get secret keycloak-admin-secret \
-o jsonpath='{.data.KEYCLOAK_ADMIN_PASSWORD}' | base64 -d && echo
Step 7: Smoke Checks
curl -k -X POST "https://kubetest.bbox-dev.de/graphql" \
-H 'Content-Type: application/json' \
-H 'X-Realm: primary' \
--data-binary '{"query":"query { __typename }"}'
Expected response:
Open in browser:
Minimal Values-File Alternative
If you prefer a values file instead of many --set flags:
# values.customer.yaml
global:
domain: kubetest.bbox-dev.de
tls:
mode: cert-manager
clusterIssuer: letsencrypt-prod
secretName: kubetest-bbox-dev-de-tls
quickstart:
adminEmail: admin@kubetest.bbox-dev.de
Install:
helm upgrade --install basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
--version 0.3.32 \
-n basebox \
--create-namespace \
--wait \
--timeout 120m \
-f values.customer.yaml
Upgrade an Existing Installation
Before upgrading, create and verify a backup of the AISRV database and retain the values files used for the installation.
Use the same TLS mode and settings as the existing installation. For example,
if values.customer.yaml contains the cert-manager configuration shown above,
upgrade with the new chart defaults and that values file:
helm upgrade basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
--version 0.3.32 \
--namespace basebox \
--reset-then-reuse-values \
--wait \
--timeout 120m \
--values values.customer.yaml
If you manage the cert-manager settings directly on the command line instead of in a values file, use:
helm upgrade basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
--version 0.3.32 \
--namespace basebox \
--reset-then-reuse-values \
--wait \
--timeout 120m \
--set global.domain=<YOUR_DOMAIN> \
--set global.tls.mode=cert-manager \
--set global.tls.clusterIssuer=<YOUR_CLUSTER_ISSUER> \
--set global.tls.secretName=<YOUR_TLS_SECRET_NAME>
Here, global.tls.secretName is the Secret that cert-manager creates and
renews; you do not create that Secret manually.
Add every other values file used by the installation, such as the optional MCP
connector values file. --reset-then-reuse-values adopts the basebox
1.8.8 image defaults while retaining existing
installation overrides.
basebox 1.8.6 adds AISRV database migration V32. Returning to an AISRV
version older than 1.8.6 requires restoring the matching pre-upgrade AISRV
database backup together with the earlier Helm release.
Troubleshooting
404on the public hostname:- check DNS and ingress host alignment
- certificate not issued:
- check
ClusterIssuer, ACME reachability, and ingress address - login callback error:
- confirm the external hostname is the same in
global.domain - GraphQL returns HTML instead of JSON:
- check ingress rules and host mapping
- image pulls fail on cluster nodes:
- check registry pull access from the runtime, not only from your workstation