Skip to main content
nao ships a Helm chart for running the container on Kubernetes. It covers the deployment, service, secrets, an optional PostgreSQL subchart, persistent volumes for context and projects, and optional autoscaling and pod disruption budgets. The chart lives in helm/ in the nao repository and is published to GHCR.

Install

--version is the chart version. The nao image tag comes from the chart’s appVersion; override it with --set image.tag=<tag> to run a different nao release without waiting for a chart release. To install from a clone of the repository instead:

Choose a context mode

config.contextSource picks where the project comes from. It maps to NAO_CONTEXT_SOURCE.
The project directory is mounted from a PersistentVolume. Pre-populate the PVC with a valid nao project - a directory containing nao_config.yaml.

Database

The chart deploys a bundled bitnami/postgresql by default. To point at your own instance, disable it and set a URI:
SQLite works for single-node or testing deployments (dbUri: "sqlite:./db.sqlite"), but use PostgreSQL for anything real.
postgresql.auth.password is empty by default. Set it before going to production, and set secrets.betterAuthSecret to a value you generated yourself.

Ingress

Set ingress.enabled=true to expose nao through an Ingress controller. At least one host with one path is required. Point config.betterAuthUrl (and any SSO redirect URIs) at the public URL the ingress serves.

External secrets and extra env vars

By default the chart renders a Secret from the secrets.* values. To load secrets from a Secret you manage yourself (GitOps, External Secrets Operator, Sealed Secrets), set existingSecret to its name. The chart then renders no Secret of its own and the whole secrets.* block is ignored, so the referenced Secret must carry the same keys (BETTER_AUTH_SECRET, DB_URI, provider API keys, and so on).
The pod-template checksum only tracks the chart-rendered Secret, so rotating an external Secret does not restart pods on its own. Pair it with a rollout trigger (stakater/reloader, ESO templated annotations) or run kubectl rollout restart after rotation.
Inject any environment variable the chart has no first-class key for with extraEnv (appended to the container) or extraEnvFrom (extra configMapRef / secretRef sources):

Values reference

The chart’s values.yaml is the full list. Any nao environment variable not exposed as a value can still be set through the chart’s config and secret templates.
Running more than one replica, permanent storage must be shared across pods: use the S3 backend, or a read-write-many volume. See Files and Storage.

Operate

Next steps

Deployment guide

Environment variables and the full self-hosting walkthrough

Deployment-managed context

How NAO_CONTEXT_SOURCE resolves the project at startup