# Install

> Part of the NocoDB documentation (Self-hosting > Installation > Kubernetes). Index of all pages: https://nocodb.com/llms.txt. Any docs page is available as Markdown by adding `.md` to its URL.

URL: https://nocodb.com/docs/self-hosting/installation/kubernetes/install
Last updated: 2026-08-17

Production installation of NocoDB on Kubernetes with the official Helm chart.

This guide installs NocoDB for production against external PostgreSQL and Redis, with object
storage for attachments connected from the admin panel after install.

## 1. Prepare your datastores

Provision a PostgreSQL database and a Redis instance. NocoDB runs its own schema migrations on
startup, so the database user needs DDL privileges on its schema. Enable TLS on PostgreSQL and
Redis where possible.

Also provision an S3-compatible bucket for attachments. You connect it from the NocoDB admin panel
after install (see [step 5](#5-configure-attachment-storage)), not through the chart, so no S3
credentials go into your Kubernetes Secret.

## 2. Create the secret

Create one Kubernetes Secret holding your connection strings and credentials. The chart reads
these keys:

| Key            | Purpose        | Example                                                   |
| -------------- | -------------- | --------------------------------------------------------- |
| `DATABASE_URL` | PostgreSQL URL | `postgresql://user:pass@host:5432/nocodb?sslmode=require` |
| `NC_REDIS_URL` | Redis URL      | `rediss://:pass@host:6379`                                |

```bash
kubectl create namespace nocodb
kubectl -n nocodb create secret generic nocodb-secrets \
  --from-literal=DATABASE_URL='postgresql://user:pass@db.internal:5432/nocodb?sslmode=require' \
  --from-literal=NC_REDIS_URL='rediss://:pass@redis.internal:6379'
```

<Callout type="tip">
  This same pattern works with the External Secrets Operator or Sealed Secrets: have your tool
  create the Secret, then point the chart at it. The JWT secret and datasource encryption key are
  auto-generated and preserved across upgrades if you do not provide them.
</Callout>

## 3. Install the chart

```bash
helm install nocodb oci://ghcr.io/nocodb/charts/nocodb --version 1.0.0 \
  -n nocodb --create-namespace -f values.yaml
```

A minimal production `values.yaml`:

```yaml
replicaCount: 2
worker:
  enabled: true
  replicaCount: 2
externalDatabase:
  existingSecret: nocodb-secrets
externalRedis:
  existingSecret: nocodb-secrets
ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: nocodb.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: nocodb-tls
      hosts: [nocodb.example.com]
```

Verify the rollout:

```bash
kubectl -n nocodb rollout status deploy/nocodb
kubectl -n nocodb exec deploy/nocodb -- wget -qO- http://localhost:8080/api/v1/health
```

## 4. Ingress and TLS

Set `ingress.enabled: true`, an `ingress.className`, and a cert-manager `cluster-issuer`
annotation (or supply your own TLS secret under `ingress.tls`). The chart derives `NC_SITE_URL`
from the first ingress host automatically, using `https` when TLS is configured; override it with `nocodb.publicUrl` if needed.

## 5. Configure attachment storage

NocoDB stores uploaded files in object storage configured from the app, not the chart. Once the
app is reachable, sign in as a super admin, open the **App Store**, and set up an S3-compatible
**Storage** plugin (AWS S3, MinIO, Google Cloud Storage, and others are supported) with your
bucket and credentials.

The setting is saved in the metadata database, so every app and worker replica picks it up
automatically. See
[App Store integrations](/docs/product/account-settings/oss-specific-details#app-store) for the
full list of supported providers.

<Callout type="warn">
  Configure object storage before users upload files. Until you do, attachments are written to local
  pod storage and are not shared across replicas.
</Callout>

## 6. High availability

The app and worker scale independently:

* **App**: scale freely. Run `replicaCount: 2`+ (requires Redis) or enable the HPA with
  `autoscaling.enabled: true`. App pods are stateless; WebSocket events fan out across replicas
  through Redis, so no sticky sessions are needed.
* **Worker**: prefer a fixed `worker.replicaCount` of 2 or more for stability (see Background workers below).
* Enable a PodDisruptionBudget with `pdb.create: true` (covers both the app and the worker).
* The chart ships a soft pod anti-affinity by default (`podAntiAffinityPreset: soft`).

## 7. Background workers

Workers process the shared Bull job queue (imports, thumbnails, migrations) and require Redis.

Run a **fixed `worker.replicaCount` of 2 or more** rather than autoscaling them. Workers run
asynchronous jobs, so scaling down (or a rolling update) terminates a pod that may be mid-job. On
shutdown NocoDB tries to finish in-flight jobs within `worker.terminationGracePeriodSeconds`
(default 120s); raise it above the duration of your longest job. If a worker is killed before it
finishes, Bull re-runs the job on another worker through stalled-job recovery, so **jobs should be
idempotent**.

Worker autoscaling is available (`worker.autoscaling.enabled: true`, floored at 2 replicas) but is
opt-in: enable it only if your jobs are short and idempotent and you have tuned the grace period.
Tune throughput with `worker.replicaCount` and `worker.concurrency`.

## 8. SSO

Set `sso.oidc.enabled: true` (or `sso.saml.enabled: true`) and provide provider client secrets
via `extraEnvVars` referencing your secret. See
[environment variables](/docs/self-hosting/environment-variables).

## 9. Observability

NocoDB does not expose a Prometheus metrics endpoint. Collect container logs with your cluster
logging stack and, optionally, set `monitoring.sentry.enabled: true` for error reporting. Pod and
cluster metrics come from the standard kube-state-metrics / cAdvisor stack.

## 10. Additional configuration

Use `extraEnvVars`, `extraVolumes`/`extraVolumeMounts`, and `extraDeploy` for anything the chart
does not model directly. For PostgreSQL with a private CA, mount the CA via `extraVolumes` and set
`NC_DB_JSON_FILE` through `extraEnvVars`.

## Production checklist

* External PostgreSQL and Redis configured; attachment storage set up in the App Store
* All credentials via `existingSecret` (no inline secrets)
* `resources` reviewed (defaults request 1 vCPU and 2 GiB memory per pod; 1 GiB memory minimum)
* `pdb.create: true` and anti-affinity in place
* `autoscaling.enabled: true` (or a fixed `replicaCount` ≥ 2)
* TLS configured via ingress
* Image tag pinned (defaults to the chart's `appVersion`)
* Database backups configured
* Readiness verified via `/api/v1/health`

## Parameters reference

See the chart `README.md` for the full parameter table.

---

## Related pages

- [Kubernetes](https://nocodb.com/docs/self-hosting/installation/kubernetes.md): Deploy NocoDB on Kubernetes with the official Helm chart for production, high-availability setups.
- [Upgrade & Backup](https://nocodb.com/docs/self-hosting/installation/kubernetes/upgrade.md): Upgrade, roll back, and back up a NocoDB Helm deployment on Kubernetes.
