Installing with Helm
Labtagon AI OS is installed with one Helm chart, deploy/helm/ai-os. This page goes through the
values you have to set, the keys and the sign-in. The chart refuses to render when a required
value is missing or two values contradict each other, so most mistakes show up before anything
reaches the cluster.
Before you start
Section titled “Before you start”- Kubernetes 1.30 or later, with a metrics server if you keep the autoscalers on.
- A Gateway API implementation with a Gateway for your host, or an Ingress controller.
- The CloudNativePG operator (
postgres.operatorNamespace, defaultcnpg-system), or a Postgres of your own with pgvector 0.8 or later. - An OpenID Connect provider. The examples use Keycloak.
- DNS and a TLS certificate for your host on the Gateway or Ingress.
- If you switch on sandboxes or sandboxed tool servers: the RuntimeClass
gvisoron the nodes that run them (instances.sandboxedRuntimeClass,sandboxes.runtimeClass).
The values you must set
Section titled “The values you must set”| Value | What |
|---|---|
global.host |
The public host of the console and of the MCP endpoint, for example ai.example.com. |
global.imageRegistry |
Where AI OS’s own component images are released. |
keycloak.issuer |
Your provider’s issuer, for Keycloak https://<keycloak>/realms/<realm>. |
keycloak.* |
The clients, scopes and claims, if yours are named otherwise than the defaults (below). |
routes.kind, routes.parentRefs |
httproute (default) with the Gateway(s) to attach to, or ingress with ingressClassName and tlsSecretName. routes.fromNamespace names the namespace of the Gateway or ingress controller for the network policies (default envoy-gateway-system). |
keys.existingSecret |
The Secret with the platform’s keys (default ai-os-keys), or keys.externalSecret.enabled: true to have the chart create an ExternalSecret. |
postgres.* |
create: true (default) makes a CloudNativePG cluster with instances: 2 and storage: 10Gi. With create: false, existingSecret names a Secret with the key uri, and port the port the network policy opens. |
storage.* |
Where files’ bytes go: garage (default, the chart runs Garage), external (any S3, with endpoint, region and a Secret with access-key-id and secret-access-key) or postgres (no object store). |
Optional, and described on its own page: global.appHost, see
App host.
A small values file:
global: host: ai.example.com imageRegistry: registry.example.com/ai-oskeycloak: issuer: https://id.example.com/realms/exampleroutes: kind: httproute parentRefs: - { name: platform, namespace: envoy-gateway-system, sectionName: https }keys: existingSecret: ai-os-keyspostgres: create: true instances: 2 storage: 10Gistorage: mode: garagehelm lint deploy/helm/ai-os -f values.yamlhelm upgrade --install ai-os deploy/helm/ai-os -n ai-os-system --create-namespace -f values.yamlAfter the install, the chart’s notes list what still has to be done outside it.
The keys
Section titled “The keys”One Secret holds the platform’s keys. Create them once; each component mounts only what it needs.
| Key | What it is | Made with |
|---|---|---|
age-identity, age-recipient |
Decrypts and encrypts the stored sign-ins and keys of tool servers (age). Only the egress gateway holds the identity. | age-keygen |
approval-signing-key, approval-verify-key |
The control API signs approvals, the controller checks them before it runs anything. The keys of LLM providers are encrypted with a key derived from the signing key. | Ed25519 key pair |
agent-token-key |
Signs the access tokens AI OS issues to clients (ADR 0059). | EC P-256 key, PKCS #8 |
session-key |
Random bytes, mounted into the MCP gateway. | random bytes |
egress-ca.crt, egress-ca.key |
The CA the egress gateway issues a certificate per host with; instances trust it. | a CA certificate and its key |
The repository’s deploy/openbao/seed-ai-os.sh keys <mount> creates all of them straight into
OpenBao without printing them, and refuses to overwrite existing ones.
Further Secrets, each optional:
storage.encryption: the storage key that wraps the keys of files. WithoutexistingSecretthe chart makes one once and keeps it (see Backups and restore).push.secretName(ai-os-push): the VAPID key pair for browser notifications. Without it there are none.fileLinks.secretName(ai-os-file-links): the key of file preview links in clients that show widgets (link-key). Without it there are no previews.modelKeys.*: API keys of the safety, decision and personal-data models the gateway asks.
Sign-in
Section titled “Sign-in”People sign in at the console through your OpenID Connect provider. Set up there:
- The console’s client
keycloak.consoleClientId(ai-os-console), confidential, with the redirect addresshttps://<app host>/api/auth/callback(without an app host:global.host). Its secret goes into the Secretkeycloak.consoleClientSecretName(ai-os-console-oidc), keyclient-secret. - The clients’ sign-in.
keycloak.agentClientslists the clients the console’s connect dialog shows, one tab each: by default Claude Code, Codex, Cursor, claude.ai, Hermes and AI OS Workbench. Each entry names a client id, a title and a built-in guide (claude-code,codex,claude-ai,cursor,generic,workbench). As long as the provider issues the clients’ tokens, each id is a public client with PKCE at the provider, and the client scopekeycloak.mcpScope(ai-os-mcp) puts the audiencekeycloak.audienceinto its tokens. - AI OS as the clients’ authorization server (ADR 0055, 0059): with
profiles.signInChooser: trueAI OS issues the clients’ tokens itself and people choose a profile when a client signs in. The provider then only signs people in at the console; no client per tool and no extra redirect address is needed.profiles.agentTokenssays whose tokens the gateway accepts:ai-os,upstreamorboth(default, while an installation moves over). - Claims.
keycloak.rolesClaim(roles) carries realm roles; the rolekeycloak.adminRole(ai-os-admin) opens the administration.keycloak.groupsClaim(groups) carries group paths such as/sales: map them with Keycloak’s group membership mapper, full paths on, into the console’s ID token and into theai-os-mcpscope. Groups in the Control Panel are made from them. - Organisations.
orgs.sourceplaces people in an organisation by the domain of their verified e-mail address (domain, default) or by a claim (claim, Keycloak’sorganization).orgs.bootstrapcreates organisations at the first start. See Organisations and sign-in. - A provider for the whole platform (
signIn.platform, ADR 0078): besides your own, for example Microsoft Entra ID for organisations without a provider of their own. - “Sign in with AI OS” for tool servers (ADR 0020): the confidential client
keycloak.connectionsClientId(ai-os-connections) with offline access and token exchange; only the token broker in the egress gateway reads its secret. Without it, this one built-in sign-in is off; other providers still work.
Images and pinning
Section titled “Images and pinning”- AI OS’s components run by tag (default: the chart’s
appVersion) unless you pin them:components.<name>.digest,bundles.fetchDigestandchecks.digest, eachsha256:and 64 hex digits. Once one component is pinned, every enabled one and the bundle fetcher must be; the chart refuses to render otherwise. - Build checks need
checks.digest(orchecks.taglocally). Without it, builds run without checks and Admin → Platform says so. - A mirror for third-party images:
global.mirror, a prefix laid out as Harbor’s proxy caches are, or{prefix, registries}. Runtimes, Presidio, Postgres, Garage, SearXNG, Docling and the images people give their servers are pulled through it.allowedRegistrieslists the upstream registries pods may pull from, always by digest.
Settings fixed by the installation
Section titled “Settings fixed by the installation”Most of AI OS’s behaviour is in settings that administrators change in the console. settings: in
the values fixes some for every organisation; the console then shows them locked. For example:
settings: instances.idleTimeout: 15m instances.idleTimeoutMax: 4h builds.allowHosts: "registry.npmjs.org,pypi.org,files.pythonhosted.org"The chart refuses an idle default that is longer than the longest allowed.
A second installation in the same cluster
Section titled “A second installation in the same cluster”global.installation names an installation (for example staging) and labels everything it
makes. It also needs its own release name, namespace, instances.namespacePrefix,
instances.orgNamespacePrefix and builds.namespace.
Checking the first start
Section titled “Checking the first start”- The controller applies the database migrations at start; wait until its pods are ready.
- Open
https://<host>/and sign in with an account that has the roleai-os-admin. - Under Administration → Platform you see the components, the database, builds and namespaces
as the controller sees them (every 15 seconds,
observe.interval). - Set up the first model provider: see Models and providers.