Install
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), 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 |
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'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.
3. Install the chart
helm install nocodb oci://ghcr.io/nocodb/charts/nocodb --version 1.0.0 \
-n nocodb --create-namespace -f values.yamlA minimal production values.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:
kubectl -n nocodb rollout status deploy/nocodb
kubectl -n nocodb exec deploy/nocodb -- wget -qO- http://localhost:8080/api/v1/health4. 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 for the full list of supported providers.
Configure object storage before users upload files. Until you do, attachments are written to local pod storage and are not shared across replicas.
6. High availability
The app and worker scale independently:
- App: scale freely. Run
replicaCount: 2+ (requires Redis) or enable the HPA withautoscaling.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.replicaCountof 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.
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) resourcesreviewed (defaults request 1 vCPU and 2 GiB memory per pod; 1 GiB memory minimum)pdb.create: trueand anti-affinity in placeautoscaling.enabled: true(or a fixedreplicaCount≥ 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.