Licensed to be used in conjunction with basebox, only.
BaseBox - Quick Start Guide
Get your BaseBox up and running in minutes using OCI Helm registry.
Prerequisites
- Kubernetes cluster already prepared
kubectlandhelminstalled on your workstation- CloudNativePG operator installed on the cluster
- NGINX ingress controller installed on the cluster
- cert-manager installed and
ClusterIssueravailable (example:letsencrypt-prod) - Basebox install bundle files available from
basebox.ai/helmtagv0.3.12underexamples/:examples/values-hetzner-gpu.example.yamlexamples/db-clusters-hetzner.yamlexamples/generate-hetzner-config.shexamples/sql/aisrv/schema.sqlexamples/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:
- 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):
Step 1: Set kubeconfig
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
bash "${EXAMPLES_DIR}/generate-hetzner-config.sh" .
mv values-hetzner-gpu.yaml values.customer.yaml
mv db-clusters-hetzner.yaml db-clusters.customer.yaml
The helper script already generates the required passwords and keeps dependent values aligned.
Edit values.customer.yaml and set:
aisrv.env.ADMIN_EMAILto the email address that should become the primary tenant admin login
Keep the generated passwords and the packaged image tags unchanged unless you intentionally want to deploy different credentials or application images.
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.
Create domain-override.yaml:
cat > domain-override.yaml <<EOF
global:
baseUrl: "https://${BASEBOX_DOMAIN}"
domain: "${BASEBOX_DOMAIN}"
ingress:
tls:
enabled: true
secretName: "${BASEBOX_DOMAIN//./-}-tls"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://${BASEBOX_DOMAIN}"
idp:
domain: "${BASEBOX_DOMAIN}"
env:
KC_HOSTNAME: "https://${BASEBOX_DOMAIN}/auth"
aisrv:
domain: "${BASEBOX_DOMAIN}"
env:
AISRV_BASE_DOMAIN: "${BASEBOX_DOMAIN}"
AISRV_OIDC_ISSUER_URL: "https://${BASEBOX_DOMAIN}/auth"
storesrv:
domain: "${BASEBOX_DOMAIN}"
frontend:
domain: "${BASEBOX_DOMAIN}"
env:
VITE_BB_OIDC_DOMAIN: "https://${BASEBOX_DOMAIN}/auth/realms/"
VITE_BB_OIDC_FORCE_REALM: "primary"
VITE_BB_GRAPHQL_URL: "https://${BASEBOX_DOMAIN}/graphql"
EOF
Verify that no placeholder domains remain in the generated files:
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.12 \
-n basebox \
-f values.customer.yaml \
-f domain-override.yaml \
--wait \
--timeout 120m
Step 8: Wait for automatic Keycloak/OIDC reconciliation
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:
Step 9: Smoke checks
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"
curl -k -X POST "https://<YOUR_DOMAIN>/graphql" \
-H "Content-Type: application/json" \
-H "X-Realm: primary" \
--data-binary '{"query":"query { __typename }"}'
Expected:
/returns200- auth URL returns login page (not
404and notInvalid parameter: redirect_uri) /graphqlreturns GraphQL JSON (not HTML and not404)
Step 11: Token checks (recommended)
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>"
Use these values from values.customer.yaml:
<PRIMARY_ADMIN_EMAIL>=aisrv.env.ADMIN_EMAIL<PRIMARY_ADMIN_PASSWORD>=aisrv.env.ADMIN_PASSWORD<KEYCLOAK_ADMIN_PASSWORD>=idp.keycloak.keycloak_admin_password
Expected:
- both token requests return
200
Troubleshooting
404on your domain whilenip.ioworks:- domain mismatch in ingress values.
- regenerate/fix
domain-override.yamland redeploy.
/graphqlreturns frontend HTML instead of GraphQL JSON:- ingress host/domain alignment is still wrong for
aisrv. - regenerate/fix
domain-override.yamland redeploy.
- ingress host/domain alignment is still wrong for
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
masterrealm
- Helm validation fails for missing secrets:
- set required values in
values.customer.yaml:AISRV_OIDC_SUPER_ADMIN_CLIENT_SECRETAISRV_OIDC_SUPER_ADMIN_PASSWORD
- set required values in