Skip to content

Configuration

This page covers AKKO's secrets management, TLS setup, deployment profiles, resource requirements, and common configuration pitfalls.


Secrets and Configuration

All secrets are managed via Kubernetes Secrets, auto-generated by Helm templates from global.auth.* values. For development, deterministic passwords are set in helm/examples/values-dev.yaml.

# View all AKKO secrets in the cluster
kubectl get secrets -n akko

# Inspect a specific secret
kubectl get secret akko-secrets -n akko -o jsonpath='{.data}' | jq

Never commit secrets

The following paths are gitignored and must never be committed:

  • traefik/certs/ -- TLS private key and certificate
  • Helm values files containing production passwords

Key Values

These values are configured in your Helm values file (e.g., helm/examples/values-dev.yaml) under global.auth.* and injected as Kubernetes Secrets:

Helm Value Path Purpose Default
global.domain Base domain for all *.domain routing akko.local
global.auth.postgresPassword PostgreSQL superuser password random
global.auth.postgresAkkoPassword akko application user password random
global.auth.minioRootUser / minioRootPassword object storage (S3) admin credentials akko-admin / random
global.auth.keycloakAdminPassword Keycloak admin console password random
global.auth.keycloakDbPassword Keycloak PostgreSQL user password random
global.auth.kcClientSecret* OAuth2 client secrets (JupyterHub, Superset, Airflow, Dashboards, oauth2-proxy, OpenMetadata) random hex
global.auth.polarisRootSecret Apache Polaris bootstrap credential random hex
global.auth.supersetSecretKey Superset Flask secret key random hex
global.auth.supersetAdminPassword Superset admin password random
global.auth.airflowAdminPassword Airflow admin password random
global.auth.airflowFernetKey Airflow Fernet encryption key random
global.auth.grafanaAdminPassword Dashboards admin password random
global.auth.jupyterhubSecretToken JupyterHub proxy auth token random hex
akko-ollama.model Default Ollama LLM model qwen2.5:3b
global.auth.omAirflowPassword OpenMetadata ingestion Airflow password random
global.auth.omIngestionBotJwt OpenMetadata bot JWT (must be replaced after first start) placeholder

Regenerating Secrets

To rotate secrets in a Kubernetes deployment, update the values in your Helm values file and run a Helm upgrade:

helm upgrade akko helm/akko/ -n akko \
  -f helm/examples/values-dev.yaml \
  --set global.auth.postgresPassword=NEW_PASSWORD \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

PostgreSQL password persistence

PostgreSQL stores passwords in its persistent volume. If you change secret values in Helm, the new passwords will not take effect for existing database users. You must manually update them:

kubectl exec -n akko deploy/akko-postgresql -- psql -U postgres -c \
  "ALTER USER akko WITH PASSWORD 'new-password';"

This applies to all database users: postgres, akko, keycloak_user.


Custom Domain

By default, AKKO uses the akko.local domain (e.g., lab.akko.local, bi.akko.local). This is configurable via global.domain in Helm values.

To use a custom domain:

  1. Set the domain in your Helm values override:

    global:
      domain: akko.example.com
    

  2. Deploy or upgrade:

    helm upgrade akko helm/akko/ -n akko -f your-values.yaml \
      --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json
    

  3. Ensure DNS resolves *.akko.example.com to your cluster's ingress IP.

Inter-service communication

All inter-service communication uses Kubernetes service DNS names (e.g., akko-akko-keycloak:8080, akko-postgresql, akko-minio:9000), never external domain URLs.


TLS Certificates

Self-signed certificates are generated automatically by scripts/generate-certs.sh:

# Generates traefik/certs/akko.crt and traefik/certs/akko.key
./scripts/generate-certs.sh

The certificate covers *.akko.local (wildcard SAN) by default. If you use a custom domain, regenerate the certs after changing global.domain.

Safari and Self-Signed Certs

Safari requires manual trust for self-signed certificates:

  1. Open Keychain Access
  2. Drag traefik/certs/akko.crt into the System keychain
  3. Double-click the certificate, expand Trust, set to Always Trust
  4. Restart Safari

Chrome and Firefox will show a warning but allow you to proceed.


Deployment Profiles

AKKO uses Helm sub-chart toggles to manage optional heavyweight services. Each sub-chart can be enabled or disabled independently in your values.yaml.

Default Profile (Core)

helm install akko helm/akko/ -n akko --create-namespace \
  -f helm/examples/values-dev.yaml \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

This deploys ~20 core services: Traefik, PostgreSQL, object storage, Polaris, Trino, Spark, JupyterHub, Superset, Airflow, Keycloak, Dashboards, Prometheus, Ollama, oauth2-proxy, cockpit, AKKO Docs, and init jobs.

Governance Profile

Enable OpenMetadata and OpenSearch in your values file:

# values-governance.yaml
openmetadata:
  enabled: true
akko-opensearch:
  enabled: true

Then deploy:

helm upgrade akko helm/akko/ -n akko \
  -f helm/examples/values-dev.yaml \
  -f values-governance.yaml \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

Or use --set flags directly:

helm upgrade akko helm/akko/ -n akko \
  -f helm/examples/values-dev.yaml \
  --set openmetadata.enabled=true \
  --set akko-opensearch.enabled=true \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

Adds OpenMetadata (server) and OpenSearch. These services are memory-intensive and require additional cluster resources.

Enterprise Profile (directory service)

Enable directory service for enterprise LDAP directory integration:

akko-lldap:
  enabled: true
helm upgrade akko helm/akko/ -n akko \
  -f helm/examples/values-dev.yaml \
  --set akko-lldap.enabled=true \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

Resource Requirements

Profile Minimum Cluster RAM Recommended
Default (core) 8 GB 10 GB
Governance 16 GB 20 GB

OpenMetadata + OpenSearch OOM

With less than 16 GB allocated to the cluster (or Docker Desktop for k3d), the governance profile services will crash in a restart loop. OpenSearch alone requires ~1 GB (heap + native memory) and will fail at 768 MB.


Rebuilding Custom Images

AKKO builds custom container images locally. After modifying their Dockerfiles, you must rebuild and push to the local registry:

# Rebuild all custom images and push to k3d registry:
bash helm/scripts/build-images.sh

# Then upgrade:
helm upgrade akko helm/akko/ -n akko -f helm/examples/values-dev.yaml \
  --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json

Pods use imagePullPolicy: Always in dev

In k3d dev mode, custom images use pullPolicy: Always so pods automatically pick up newly pushed images on restart. To trigger a rollout after pushing new images:

kubectl rollout restart deploy/<service-name> -n akko

Version Pinning

Every container image uses an explicit version tag. There are zero latest tags in the Helm chart. This ensures reproducible deployments and makes it clear exactly which versions are running.

The cockpit Tech Stack display is generated dynamically by scripts/generate-versions.sh, which writes branding/cockpit/versions.json.

./scripts/generate-versions.sh

Startup Sequence

The recommended way to start AKKO is through the deploy script:

bash helm/scripts/deploy.sh

This script performs the following steps in order:

  1. Create k3d cluster -- creates the k3d cluster with a local registry (skips if it already exists)
  2. Generate TLS certs -- runs generate-certs.sh (skips if certs exist)
  3. Build custom images -- builds and pushes akko-postgres, akko-spark, akko-notebook, akko-cockpit to the k3d registry
  4. Generate versions manifest -- runs generate-versions.sh
  5. Deploy with Helm -- runs helm install akko helm/akko/ -n akko --create-namespace -f helm/examples/values-dev.yaml --set-file akko-keycloak.realm.data=helm/examples/realm-akko-k3d.json
  6. Print URLs -- displays all service URLs

Init jobs (postgres-init, polaris-init, minio-init, superset-init) run automatically as Kubernetes init containers and are idempotent -- they create databases, catalogs, buckets, and dashboards only if they do not already exist.