Skip to content

BaseBox - Quick Start Guide

Get your BaseBox up and running in minutes using OCI Helm registry.

Prerequisites

  • Kubernetes cluster already prepared
  • kubectl and helm installed on your workstation
  • CloudNativePG operator installed on the cluster
  • NGINX ingress controller installed on the cluster
  • cert-manager installed and ClusterIssuer available (example: letsencrypt-prod)
  • Basebox install bundle files available from basebox.ai/helm tag v0.3.7 under examples/:
    • examples/values-hetzner-gpu.example.yaml
    • examples/db-clusters-hetzner.yaml
    • examples/sql/aisrv/schema.sql
    • examples/sql/aisrv/initdb.sql
    • If you run from this monorepo layout, the same files are under helm/examples/

Pull Example Files

To get the example files, do:

helm pull oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai --version 0.3.7
tar -xzf basebox.ai-0.3.7.tgz basebox.ai/examples
ls -R basebox.ai/examples
  • Registry credentials for gitea.basebox.health

Registry Credentials

Our container registry is public, but if you pull containers from a Kubernetes cluster (containerd), you still need to provide registry credentials. This seems to be a bug either in containerd or our registry server.

If you get permission denied errors, please use this token (username pacman):

ee4d3d1bad18cae07a1817701d2281f6fbf8aa2f

Step 1: Set kubeconfig

export KUBECONFIG="<PATH_TO_KUBECONFIG>"
kubectl cluster-info

See the commands under Server Preparation, Step 7 for instructions on how to create the KUBECONFIG file.

Step 2: Prepare install files

EXAMPLES_DIR="<PATH_TO_EXAMPLES_DIR>"   # examples or helm/examples
cp "${EXAMPLES_DIR}/values-hetzner-gpu.example.yaml" values.customer.yaml
cp "${EXAMPLES_DIR}/db-clusters-hetzner.yaml" db-clusters.customer.yaml

Edit values.customer.yaml and set at least:

  • idp.keycloak.keycloak_admin_password
  • idp.keycloak.init.admin_password
  • aisrv.env.AISRV_OIDC_SUPER_ADMIN_CLIENT_SECRET
  • aisrv.env.AISRV_OIDC_SUPER_ADMIN_PASSWORD
  • keep inference.image.tag: v1.6.2 for this validated baseline

Edit db-clusters.customer.yaml and replace all CHANGE_ME_DB_PASSWORD.

Step 3: Create namespace and image pull secret

kubectl create ns basebox --dry-run=client -o yaml | kubectl apply -f -

kubectl -n basebox create secret docker-registry regcred-bb \
  --docker-server=gitea.basebox.health \
  --docker-username='<REGISTRY_USERNAME_OR_EMAIL>' \
  --docker-password='<REGISTRY_PASSWORD_OR_TOKEN>' \
  --docker-email='<EMAIL>' \
  --dry-run=client -o yaml | kubectl apply -f -

Step 4: Create database clusters

kubectl apply -f db-clusters.customer.yaml

kubectl -n basebox wait --for=condition=Ready cluster.postgresql.cnpg.io/aisrv-db --timeout=20m
kubectl -n basebox wait --for=condition=Ready cluster.postgresql.cnpg.io/idp-db --timeout=20m
kubectl -n basebox wait --for=condition=Ready cluster.postgresql.cnpg.io/storesrv-db --timeout=20m

Step 5: Initialize AISRV schema (clean install)

AISRV_DB_POD="$(kubectl -n basebox get pod -l cnpg.io/cluster=aisrv-db -o jsonpath='{.items[0].metadata.name}')"
EXAMPLES_DIR="<PATH_TO_EXAMPLES_DIR>"   # examples or helm/examples

cat "${EXAMPLES_DIR}/sql/aisrv/schema.sql" | kubectl -n basebox exec -i "$AISRV_DB_POD" -- psql -v ON_ERROR_STOP=1 -U postgres -d aisrv
cat "${EXAMPLES_DIR}/sql/aisrv/initdb.sql" | kubectl -n basebox exec -i "$AISRV_DB_POD" -- psql -v ON_ERROR_STOP=1 -U postgres -d aisrv

Step 6: Create domain override file

Set your domain once and keep all components aligned.

export BASEBOX_DOMAIN="<YOUR_DOMAIN>"

Create domain-override.yaml:

global:
  baseUrl: "https://<YOUR_DOMAIN>"
  domain: "<YOUR_DOMAIN>"
  ingress:
    tls:
      enabled: true
      secretName: "<YOUR_DOMAIN_WITH_DASHES>-tls"
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
      nginx.ingress.kubernetes.io/cors-allow-origin: "https://<YOUR_DOMAIN>"
idp:
  domain: "<YOUR_DOMAIN>"
  env:
    KC_HOSTNAME: "<YOUR_DOMAIN>"
aisrv:
  domain: "<YOUR_DOMAIN>"
  env:
    AISRV_BASE_DOMAIN: "<YOUR_DOMAIN>"
    AISRV_OIDC_ISSUER_URL: "https://<YOUR_DOMAIN>/auth"
storesrv:
  domain: "<YOUR_DOMAIN>"
frontend:
  domain: "<YOUR_DOMAIN>"
  env:
    VITE_BB_OIDC_DOMAIN: "https://<YOUR_DOMAIN>/auth/realms/"
    VITE_BB_OIDC_FORCE_REALM: "primary"
    VITE_BB_GRAPHQL_URL: "https://<YOUR_DOMAIN>/graphql"

Replace <YOUR_DOMAIN> before use.

Step 7: Install Helm chart from OCI

# Login is optional; in case you get a permission denied error, use this login.
# See top info box for the token
helm registry login gitea.basebox.health -u pacman

helm upgrade --install basebox oci://gitea.basebox.health/basebox-distribution/helm/basebox.ai \
  --version 0.3.7 \
  -n basebox \
  -f values.customer.yaml \
  -f domain-override.yaml \
  --wait \
  --timeout 120m

Step 8: Wait for automatic Keycloak/OIDC reconciliation

kubectl -n basebox wait --for=condition=complete job/idp-keycloak-bootstrap --timeout=10m

This hook does both automatically: - syncs master/admin password to Helm value idp.keycloak.keycloak_admin_password - creates/updates primary/aiclient redirect/web-origin for your domain

If hook fails:

kubectl -n basebox logs job/idp-keycloak-bootstrap

Step 9: Smoke checks

kubectl -n basebox get pods -o wide
kubectl -n basebox get ingress
helm status basebox -n basebox

Expected:

  • All pods Running/Ready
  • Ingress host is exactly <YOUR_DOMAIN>

Step 10: Access checks

curl -I "https://<YOUR_DOMAIN>/"
curl -k -I "https://<YOUR_DOMAIN>/auth/realms/primary/protocol/openid-connect/auth?client_id=aiclient&redirect_uri=https%3A%2F%2F<YOUR_DOMAIN>%2Foidc%2Fcallback&response_type=code"

Expected:

  • / returns 200
  • auth URL returns login page (not 404 and not Invalid parameter: redirect_uri)
curl -k -X POST "https://<YOUR_DOMAIN>/auth/realms/primary/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "client_id=aiclient" \
  --data-urlencode "grant_type=password" \
  --data-urlencode "username=<PRIMARY_ADMIN_EMAIL>" \
  --data-urlencode "password=<PRIMARY_ADMIN_PASSWORD>"

curl -k -X POST "https://<YOUR_DOMAIN>/auth/realms/master/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "client_id=admin-cli" \
  --data-urlencode "grant_type=password" \
  --data-urlencode "username=admin" \
  --data-urlencode "password=<KEYCLOAK_ADMIN_PASSWORD>"

Expected:

  • both token requests return 200

Troubleshooting

  • 404 on your domain while nip.io works:
    • domain mismatch in ingress values.
    • regenerate/fix domain-override.yaml and redeploy.
  • Invalid parameter: redirect_uri:
    • check post-install hook status/logs:
    • kubectl -n basebox logs job/idp-keycloak-bootstrap
  • Keycloak admin password mismatch after install:
    • check post-install hook logs for:
    • Syncing master admin password...
    • then retry token check against master realm
  • Helm validation fails for missing secrets:
    • set required values in values.customer.yaml:
      • AISRV_OIDC_SUPER_ADMIN_CLIENT_SECRET
      • AISRV_OIDC_SUPER_ADMIN_PASSWORD
  • Inference startup issues on this baseline:
    • use inference.image.tag: v1.6.2 (validated).

Additional Resources