> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getnao.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes (Helm)

> Deploy nao on a Kubernetes cluster with the official Helm chart

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/`](https://github.com/getnao/nao/tree/main/helm) in the nao repository and is published to GHCR.

## Install

```bash theme={null}
helm install nao oci://ghcr.io/getnao/nao/charts/nao --version 0.1.0 \
  --namespace nao --create-namespace \
  --set secrets.betterAuthSecret="$(openssl rand -base64 32)"
```

`--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:

```bash theme={null}
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm dependency update ./helm

helm install nao ./helm \
  --namespace nao --create-namespace \
  --set secrets.betterAuthSecret="$(openssl rand -base64 32)"
```

## Choose a context mode

`config.contextSource` picks where the project comes from. It maps to [`NAO_CONTEXT_SOURCE`](/nao-agent/self-hosting/context-source).

<Tabs>
  <Tab title="local (default)">
    The project directory is mounted from a PersistentVolume. Pre-populate the PVC with a valid nao project - a directory containing `nao_config.yaml`.

    ```yaml theme={null}
    config:
      contextSource: local
      contextPath: /app/project

    persistence:
      enabled: true
      size: 1Gi
      # existingClaim: my-nao-context-pvc
    ```
  </Tab>

  <Tab title="git">
    The project is cloned from a repository at pod startup, and optionally pulled again on a schedule.

    ```yaml theme={null}
    config:
      contextSource: git
      contextPath: /app/project
      contextGitUrl: https://github.com/your-org/your-nao-project.git
      contextGitBranch: main
      refreshSchedule: "0 * * * *"   # optional, pull every hour

    secrets:
      contextGitToken: ghp_...        # required for private repositories
    ```
  </Tab>

  <Tab title="api">
    Projects are pushed dynamically with [`nao deploy`](/nao-agent/cloud/deploy). A writable volume is created at `/app/projects`.

    ```yaml theme={null}
    config:
      contextSource: api

    projectsPersistence:
      enabled: true
      size: 5Gi
    ```
  </Tab>
</Tabs>

## Database

The chart deploys a bundled `bitnami/postgresql` by default. To point at your own instance, disable it and set a URI:

```yaml theme={null}
postgresql:
  enabled: false

secrets:
  dbUri: "postgres://user:password@my-postgres-host:5432/nao"
```

SQLite works for single-node or testing deployments (`dbUri: "sqlite:./db.sqlite"`), but use PostgreSQL for anything real.

<Warning>
  `postgresql.auth.password` is empty by default. Set it before going to production, and set `secrets.betterAuthSecret` to a value you generated yourself.
</Warning>

## Values reference

| Key                                        | Default                   | Description                                                           |
| ------------------------------------------ | ------------------------- | --------------------------------------------------------------------- |
| `replicaCount`                             | `1`                       | Number of pod replicas                                                |
| `image.repository`                         | `getnao/nao`              | Container image repository                                            |
| `image.tag`                                | `""` (chart `appVersion`) | Image tag                                                             |
| `image.pullPolicy`                         | `IfNotPresent`            | Image pull policy                                                     |
| `config.serverPort`                        | `"5005"`                  | Port the backend listens on                                           |
| `config.betterAuthUrl`                     | `"http://localhost:5005"` | Public URL used for auth callbacks                                    |
| `config.contextSource`                     | `"local"`                 | Context mode: `local`, `git`, or `api`                                |
| `config.contextPath`                       | `"/app/project"`          | Mount path for the nao project                                        |
| `config.contextGitUrl`                     | `""`                      | Repository URL (git mode)                                             |
| `config.contextGitBranch`                  | `"main"`                  | Branch to clone (git mode)                                            |
| `config.refreshSchedule`                   | `""`                      | Cron expression for a periodic git pull                               |
| `config.dbSsl`                             | `false`                   | Require TLS on the database connection                                |
| `config.enableUserLogin`                   | `true`                    | Email and password login                                              |
| `config.enableUserSignup`                  | `false`                   | Allow self sign-up                                                    |
| `config.defaultUserRole`                   | `"user"`                  | Role for new users: `admin`, `user`, or `viewer`                      |
| `config.githubSso`                         | `false`                   | Enable "Sign in with GitHub"                                          |
| `config.gitlabSso`                         | `false`                   | Enable "Sign in with GitLab"                                          |
| `config.gitlabBaseUrl`                     | `""`                      | Self-hosted GitLab instance URL                                       |
| `config.betaAutomationsEnabled`            | `true`                    | [Automations](/nao-agent/chat/capabilities/automations)               |
| `config.betaContextRecommendationsEnabled` | `false`                   | [Recommendations](/nao-agent/context-engineering/recommendations)     |
| `secrets.betterAuthSecret`                 | `""`                      | **Required.** Auth session secret                                     |
| `secrets.openaiApiKey`                     | `""`                      | OpenAI API key                                                        |
| `secrets.anthropicApiKey`                  | `""`                      | Anthropic API key                                                     |
| `secrets.naoLicense`                       | `""`                      | Enterprise license, required for the SSO providers                    |
| `secrets.redisUrl`                         | `""`                      | Redis connection string                                               |
| `secrets.dbUri`                            | `""`                      | Database URI (ignored when `postgresql.enabled=true`)                 |
| `secrets.contextGitToken`                  | `""`                      | Git token for private repositories                                    |
| `service.type`                             | `ClusterIP`               | Kubernetes service type                                               |
| `service.port`                             | `80`                      | Service port                                                          |
| `resources.requests`                       | `500m` CPU, `512Mi`       | Requests                                                              |
| `resources.limits`                         | `2` CPU, `2Gi`            | Limits                                                                |
| `autoscaling.enabled`                      | `false`                   | Enable the HorizontalPodAutoscaler (`minReplicas` 1, `maxReplicas` 5) |
| `podDisruptionBudget.enabled`              | `false`                   | Enable the PodDisruptionBudget                                        |
| `persistence.enabled`                      | `false`                   | Context PVC (local mode)                                              |
| `projectsPersistence.enabled`              | `false`                   | Projects PVC (api mode)                                               |
| `postgresql.enabled`                       | `true`                    | Deploy the bundled PostgreSQL                                         |

The chart's [`values.yaml`](https://github.com/getnao/nao/blob/main/helm/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.

<Note>
  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](/nao-agent/chat/capabilities/files-and-storage#configuring-storage).
</Note>

## Operate

```bash theme={null}
helm upgrade nao ./helm --namespace nao -f my-values.yaml   # upgrade
helm history nao --namespace nao                            # revisions
helm rollback nao <revision> --namespace nao                # roll back
helm test nao --namespace nao                               # connection test
```

## Next steps

<CardGroup cols={2}>
  <Card title="Deployment guide" icon="docker" href="/nao-agent/self-hosting/deployment-guide">
    Environment variables and the full self-hosting walkthrough
  </Card>

  <Card title="Deployment-managed context" icon="code-branch" href="/nao-agent/self-hosting/context-source">
    How `NAO_CONTEXT_SOURCE` resolves the project at startup
  </Card>
</CardGroup>
