The supported installation path is the Helm chart oci://docker.io/tessarac/ai-cost-optimizer. Pulls are anonymous.
Before you start
- A Kubernetes cluster,
kubectland Helm 3 with OCI support. - A StorageClass that provisions ReadWriteOnce volumes (
kubectl get storageclass). Without one, the datastore volumes stayPending. - An ingress controller, and a DNS name and TLS certificate for the console, for example
acog.example.com. - An SMTP relay.
- Your licence file and password.
1. Choose the chart version
Use the newest release unless you have a reason not to. Releases are numbered 1.x.y; versions ending in -beta.N are pre-releases and are never chosen unless you name them.
helm show chart oci://docker.io/tessarac/ai-cost-optimizer
export CHART_VERSION=<version>
helm pull oci://docker.io/tessarac/ai-cost-optimizer --version "$CHART_VERSION" --untar
The pulled chart contains values-selfhost.yaml, the vendor overlay for self-hosted installations. It pins the images that go together for this version; read it before every install or upgrade.
2. Write your own overlay
Keep your settings in a file of your own, layered after the vendor overlay. Generate the secrets first:
openssl rand -base64 32 # ACOG_CREDS_KEY
openssl rand -hex 32 # ACOG_OPERATOR_TOKEN
openssl rand -hex 32 # ACOG_INGEST_TOKEN
my-install.yaml:
# Run the datastores as plain Deployments inside this release.
# The vendor overlay enables the high-availability topology, which needs four
# cluster-wide operators. Turn it off unless you have installed them.
ha:
enabled: false
infra:
bundled:
storageClass: "<your-rwo-storageclass>"
postgres:
password: "<DB_PASSWORD>"
clickhouse:
password: "<CH_PASSWORD>"
secret:
ACOG_POSTGRES_DSN: "postgres://aco:<DB_PASSWORD>@aco-postgres:5432/aco?sslmode=disable"
ACOG_CLICKHOUSE_PASSWORD: "<CH_PASSWORD>"
ACOG_CREDS_KEY: "<base64 key>"
ACOG_OPERATOR_TOKEN: "<hex token>"
ACOG_INGEST_TOKEN: "<hex token>"
services:
controlplane:
extraEnv:
ACOG_ENVIRONMENT: "production"
ACOG_SELF_SERVE_SIGNUP: "false"
ACOG_WEB_ORIGIN: "https://acog.example.com"
ACOG_PUBLIC_BASE_URL: "https://acog.example.com"
ACOG_TRUSTED_PROXY_CIDRS: "10.0.0.0/8"
ACOG_EMAIL_PROVIDER: "smtp"
ACOG_EMAIL_FROM: "no-reply@example.com"
ACOG_SMTP_HOST: "smtp.example.com"
ACOG_SMTP_PORT: "587"
ACOG_BOOTSTRAP_ADMIN_EMAIL: "admin@example.com"
metering:
extraEnv:
ACOG_ENVIRONMENT: "production"
ingress:
enabled: true
className: "<your-ingress-class>"
annotations: # for ingress-nginx; see below
nginx.ingress.kubernetes.io/proxy-read-timeout: "660"
nginx.ingress.kubernetes.io/proxy-send-timeout: "660"
nginx.ingress.kubernetes.io/proxy-body-size: "64m"
hosts:
- { host: acog.example.com, service: web, port: 8080 }
tls:
- hosts: [acog.example.com]
secretName: acog-example-com-tls
Give the ingress a 660-second idle timeout and a 64 MiB body limit. Common defaults are too tight for a gateway: ingress-nginx stops reading after 60 seconds and refuses bodies over 1 MiB, and an AWS load balancer closes connections idle for 60 seconds. With those defaults, long non-streaming replies and held batch requests are cut off, and large prompts are refused. 660 seconds is above the batch hold window (600 by default) and below 700 seconds, the web tier’s keep-alive; a longer idle timeout makes the load balancer reuse connections the web tier has closed, and returns occasional 502s. With the AWS Load Balancer Controller, use alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=660.
Every setting is explained in Configuration. Keep SMTP credentials and other secrets out of the file: put them in the infra Secret, or manage that Secret yourself with infra.existingSecret.
ACOG_CREDS_KEY encrypts every stored provider credential. Back it up. If it is lost, every stored credential must be entered again.
3. Render and check
Render before you install, and confirm that no operator custom resources appear and that the images are the ones you expect:
helm template aco oci://docker.io/tessarac/ai-cost-optimizer --version "$CHART_VERSION" \
-n aco -f values-selfhost.yaml -f my-install.yaml \
| grep -E '^kind:|image:' | sort -u
If you see kind: Cluster, kind: Milvus, kind: Dragonfly or kind: ClickHouseInstallation, ha.enabled is still on.
4. Install
Use release name aco and namespace aco unless you have a reason not to (the database address in the overlay above assumes the release name aco).
helm install aco oci://docker.io/tessarac/ai-cost-optimizer \
--version "$CHART_VERSION" \
-n aco --create-namespace \
-f values-selfhost.yaml \
-f my-install.yaml
The control plane applies the database schema on start. Wait for it:
kubectl -n aco rollout status deploy/aco-controlplane
5. Sign in as the first administrator
On a new database, the control plane creates ACOG_BOOTSTRAP_ADMIN_EMAIL as an administrator with a random one-time password, and prints it once in its log:
kubectl -n aco logs deploy/aco-controlplane | grep BREAKGLASS
Sign in at your console address with it. You are asked to choose your own password immediately. This happens only while no user can sign in; an established installation is never touched.
If you are ever locked out, set ACOG_BOOTSTRAP_FORCE=true to reset that account’s password and print it again, then set it back to false immediately, or every restart resets the account.
6. Load your licence
Go to Admin → Billing, upload the .acog-license file and enter its password. No restart is needed. See Licensing, including the declarative option for air-gapped and GitOps installs.
7. Connect a provider and test
Follow the Quickstart from step 2, with your own address in place of acog.tessarac.com.
Air-gapped installation
Nothing at runtime needs the internet, so an air-gapped installation differs only in where images come from:
- Render the chart with your overlays and collect the image list (
grep image:as above). - Copy each image to your registry with all of its architectures (
crane copyorskopeo copy --all), keeping the same repository names. - Point the chart at your registry with
global.registry,global.imagePullSecretsandinfra.bundled.<store>.image, render again and check.
Do this again for each new chart version before upgrading. The helm test pod uses curlimages/curl, which cannot be redirected by a value; mirror it or skip helm test.