Overview
ToolJet is an open-source, low-code platform for building internal tools: a visual app builder with 50+ datasource connectors, workflows, and the built-in ToolJet Database. This template deploys the ToolJet server — UI and API on port3000, with PostgREST and a fallback Redis bundled inside the image — backed by a bundled PostgreSQL that holds both the application database and the ToolJet Database. The default is a single replica; tooljet.replicas scales out once the optional Redis is enabled.
What Gets Created
Prerequisites
Two dictionary secrets must exist before installing: the bundled database’s credentials, and ToolJet’s three root-of-trust keys. Their values never pass through Helm values.Create the database credentials secret
tooljet_db database alongside):postgres.config.credentialsSecretName to this name. Keep the password URL-safe (letters, digits, -, _) — ToolJet places it in a connection URL as-is. PostgreSQL reads the secret only when its data directory is first initialized; see Rotating the Database Password for changing it later.Create the key secret
secrets.name to this name. Secrets are org-level, so no GVC flag is involved.Back the keys up outside Control Plane
SECRET_KEY_BASE and LOCKBOX_MASTER_KEY are write-once: rotating LOCKBOX_MASTER_KEY makes every datasource credential ToolJet has stored undecryptable. Keep a copy of all three values somewhere safe.password and name it in redis.redis.auth.fromSecret.name (with redis.redis.auth.fromSecret.enabled: true). Redis, its Sentinel and ToolJet all read it:
- Authenticated SMTP — a dictionary secret holding
SMTP_USERNAMEandSMTP_PASSWORD, and a decision made before installing, because ToolJet only picks up mail settings on its first boot. See Email. - Scheduled database backups — a bucket and cloud account for the bundled PostgreSQL. See Backing Up.
Installation
Once your key and database credentials secrets exist, install from the marketplace registry, pointing the chart at them:smtp.* values to this first install as well (see Email).
Other ways to install and manage the template:
UI
CLI
Terraform
Pulumi
Configuration
ToolJet Server
tooljet.host only when you serve ToolJet on a custom domain; leave it empty and ToolJet derives its public URL from the workload’s canonical endpoint.
Key Secret
smtp.auth.secretName to its name. The ToolJet identity is granted reveal on exactly that secret.
Access
publicAccess.enabled: false there is no public endpoint; external requests are refused and only workloads allowed by internalAccess reach ToolJet (plus your own machine through a tunnel — see Connecting).
Bundled PostgreSQL
Bundled Redis
redis.enabled: true deploys the redis template and points ToolJet at it; it is required for more than one ToolJet replica (see Scaling and Availability). With redis.redis.auth.fromSecret.enabled: true Redis, Sentinel and ToolJet read the password from the prerequisite secret named by redis.redis.auth.fromSecret.name (see Prerequisites), which the ToolJet identity is granted reveal on.
Connecting
publicAccess.enabled: false there is no public endpoint; reach the UI from your machine through a tunnel instead and open http://localhost:3000:
First Run
ToolJet ships no default account. The first person to open the endpoint completes the Super Admin onboarding and creates the initial workspace — and with the defaultpublicAccess.enabled: true that form is reachable by anyone who finds the endpoint, so claim it as soon as the workload reports ready.
Wait for the ToolJet workload to report ready
Open the endpoint and complete the Super Admin form
Invite your team
Operations
Backing Up
The bundled PostgreSQL is the postgres template, so its scheduled backup is available here under thepostgres key — nothing extra to install. It is off by default. Enabling it adds the cron workload RELEASE_NAME-postgres-backup, which uploads a gzipped SQL dump of the whole instance (all three databases) to your bucket under the configured prefix.
gcp / minio value blocks are on the postgres template page under Backup Prerequisites; use the same keys here, nested under postgres.backup.
The dump does not cover your three keys — they live in the secret you created, so back that up separately. The PostgreSQL volume set RELEASE_NAME-pg-vs also takes a final volume set snapshot when the release is uninstalled, retained for 7 days.
Restoring a Backup
Each backup is a gzipped plain-SQL dump of the whole PostgreSQL instance. Restoring means replaying that SQL into the bundled PostgreSQL, following the restore procedure on the postgres template page againstRELEASE_NAME-postgres.GVC_NAME.cpln.local with the credentials from your postgres.config.credentialsSecretName secret. From a client without network access to the GVC, the one transport that carries a dump into the container intact is cpln workload exec with --stdin and a base64 wrapper on both ends — raw binary piped through exec is corrupted:
CREATE ROLE and CREATE DATABASE statements, so a straight replay collides with the databases ToolJet already created and migrated on first boot; and no ToolJet replica may be connected while you drop and recreate those databases before the replay.
Upgrading from 1.0.0
Version 1.1.0 adopted thepostgres 3.4.1 template, which stopped taking database credentials as values. postgres.config.username, .password and .database were removed: put the values your database was initialized with into the database credentials secret under Prerequisites (keys username, password, database), set postgres.config.credentialsSecretName to its name, and remove the three keys. The key secret is unchanged.
Keep the same values so the running database still matches. A values file that still carries an old key fails the render with the postgres template’s message — config.username was REMOVED in postgres 3.4.0 — which tells you to create a dictionary secret; that is correct here too. Then continue with the sections below.
Upgrading from 1.1.0
Version 1.2.0 changes no values. The ToolJet container now starts through a chart-provided script that waits until PostgreSQL actually accepts connections before running the image’s own entrypoint, which removes a failed first attempt that earlier versions logged on a fresh install. Upgrade in place, then continue with Upgrading from 1.2.0.helm upgrade after an install can restart the bundled PostgreSQL even when nothing about it changed, which interrupts ToolJet briefly; later upgrades of the same release do not.Upgrading from 1.2.0
Version 1.3.0 removedpostgres.credentials: the database credentials are now a prerequisite secret, the same one the postgres template requires on its own. Carrying the old key forward fails the render.
1.2.0 created the database secret itself (and a second copy, RELEASE_NAME-tooljet-db), so this upgrade deletes both. Before upgrading, create a secret under a new name holding the values your database was initialized with — not new ones, or ToolJet loses its database connection:
postgres.config.credentialsSecretName set to that name and postgres.credentials removed. Your current values are in postgres.credentials of the 1.2.0 release, and also in the old secret named by its postgres.config.credentialsSecretName (cpln secret reveal SECRET_NAME -o yaml) until the upgrade deletes it.
If you ran 1.2.0 with Redis auth on, redis.redis.auth.password was removed too (carrying it forward fails the render), and the chart-created RELEASE_NAME-redis-auth-password secret is deleted by the upgrade. Copy your current Redis password into a secret under a new name first:
redis.redis.auth.fromSecret.enabled: true and redis.redis.auth.fromSecret.name to the new name, and remove redis.redis.auth.password. With Redis auth off in 1.2.0 (the default), just remove redis.redis.auth.password from your values.
The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so ToolJet briefly loses its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in get-deployments reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself.
Rotating the Database Password
Editing the secret alone does nothing to the database, and a running workload keeps the values it started with. Change one key and keep the others with export, edit, apply:ALTER ROLE for the secret’s username in PostgreSQL first (URL-safe characters only), then update the secret, then right away force a redeployment of ToolJet, and wait until get-deployments shows a higher version number, alone and ready (right after the command the status may not show the restart yet, and ready: true alone can still describe the old replica). Do not redeploy the database: PostgreSQL reads the secret only when it is first initialized, so restarting it only adds downtime. Connections the app already has open keep working after ALTER ROLE; new ones fail until its redeploy finishes, so redeploy right away and rotate in a quiet window.
Rotating the Redis Password
Only with Redis auth on. Redis keeps no password on disk, but a running Sentinel holds the one it started with, so a new password is applied live in three places before ToolJet restarts. Each Redis node first accepts both passwords, which keeps replication and every connected client working throughout.rx and sx run a command on one Redis node or Sentinel (LOCATION is your GVC’s location; nodes and Sentinels are numbered from 0 up to redis.redis.replicas and redis.sentinel.replicas minus one):
tooljet.replicas of 2 or more it rolls one replica at a time). Redis and Sentinel need no restart: when they next start they read the new password from the secret.
Scaling and Availability
tooljet.replicas sets how many ToolJet replicas run. With more than one replica, all replicas must share one Redis for the job queue and for multiplayer coordination in the app editor, so redis.enabled must be true — the single-instance Redis bundled in the image cannot be shared. Sessions are valid on every replica, so no sticky routing is needed.
tooljet.replicas of 2 or more while redis.enabled is false. The database tier is a single PostgreSQL instance by design; the Redis tier is pinned to one data node and one monitor-only Sentinel because ToolJet’s Redis client is not Sentinel-aware.
Troubleshooting
Deployment never becomes ready and the logs are empty
Deployment never becomes ready and the logs are empty
cpln helm install reported success, cpln logs returns nothing, and cpln workload get-deployments RELEASE_NAME-tooljet --gvc GVC_NAME -o yaml shows The secret KEYS_SECRET_NAME no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. under status.versions[].message.Cause: The key secret named by secrets.name or the database credentials secret named by postgres.config.credentialsSecretName does not exist. The same applies to an smtp.auth.secretName or redis.redis.auth.fromSecret.name that was set but never created. Check RELEASE_NAME-postgres and RELEASE_NAME-redis the same way.Fix: Create it (see Prerequisites). The deployment recovers on its own once the secret exists; cpln workload force-redeployment RELEASE_NAME-tooljet --gvc GVC_NAME skips the wait.Container restarts with exit code 137 and never finishes migrating
Container restarts with exit code 137 and never finishes migrating
cpln workload get-deployments RELEASE_NAME-tooljet --gvc GVC_NAME -o yaml shows an exit code of 137, and the logs end partway through the schema migrations.Cause: tooljet.resources.maxMemory was set below 4Gi. The image bakes a 4096 MB Node heap and the first-boot migrations exceed smaller limits, so the container is killed for running out of memory.Fix: Restore tooljet.resources.maxMemory: 4Gi and upgrade. The migrations complete on the next boot.Render fails because replicas above 1 require Redis
Render fails because replicas above 1 require Redis
tooljet: tooljet.replicas >= 2 requires redis.enabled=true — multiple replicas must share an external Redis for job-queue and multiplayer coordination (the in-image Redis is single-instance-only).Cause: tooljet.replicas is 2 or more while redis.enabled is false.Fix: Set redis.enabled: true (see Scaling and Availability), or keep a single replica.Render fails because the Redis replica counts must stay 1
Render fails because the Redis replica counts must stay 1
tooljet: redis.redis.replicas must stay 1 — ToolJet is not Sentinel-aware ... or tooljet: redis.sentinel.replicas must stay 1 — with a single data node there is no failover target ....Cause: redis.redis.replicas or redis.sentinel.replicas was changed from 1.Fix: Set both back to 1. ToolJet connects to the Redis service name directly, so extra data nodes would receive writes they cannot accept.SMTP was enabled through an upgrade but no email is sent
SMTP was enabled through an upgrade but no email is sent
smtp.enabled: true was applied with helm upgrade, the SMTP_* variables are on the workload, yet invitations and password resets send nothing and the instance still reports mail as disabled.Cause: ToolJet seeds its mail settings from the environment during a first-boot migration only. Values added later reach the container but are never applied.Fix: SMTP has to be part of the initial install (see Email). Enabling it on an existing instance through values is not supported by this template.Upgrade from 1.0.0 fails asking you to create a dictionary secret
Upgrade from 1.0.0 fails asking you to create a dictionary secret
config.username was REMOVED in postgres 3.4.0 and advice about a prerequisite dictionary secret.Cause: Your values file still carries postgres.config.username, postgres.config.password, or postgres.config.database.Fix: Move their values into the database credentials secret as described in Upgrading from 1.0.0.Upgrade from 1.2.0 fails because postgres.credentials was removed
Upgrade from 1.2.0 fails because postgres.credentials was removed
postgres.credentials was removed in 1.3.0 or redis.redis.auth.password was removed in tooljet 1.3.0.Cause: Your values file still carries the 1.2.0 database or Redis password keys.Fix: Follow Upgrading from 1.2.0.Logs repeat Invalid License Key and the health check reports an invalid license
Logs repeat Invalid License Key and the health check reports an invalid license
Invalid License Key:Parse error, and /api/health reports the license as invalid or expired.Cause: The image is ToolJet’s LTS build, which includes the licensed edition’s code but runs the free tier without a license key. The license check logs this on every pass.Fix: None needed — this is the free tier working as intended. The same applies to npm warn using --force lines from the image’s entrypoint.Important Notes
- Create every prerequisite secret before installing — the key secret (
secrets.name, withSECRET_KEY_BASE,LOCKBOX_MASTER_KEY, andPGRST_JWT_SECRET), the database credentials secret (postgres.config.credentialsSecretName) and, with Redis auth on, the Redis password secret. A missing secret wedges the deployment silently;status.versions[].messageincpln workload get-deployments RELEASE_NAME-tooljet --gvc GVC_NAME -o yamlnames it. SECRET_KEY_BASEandLOCKBOX_MASTER_KEYare write-once — rotatingLOCKBOX_MASTER_KEYmakes every stored datasource credential undecryptable. Back the keys up outside Control Plane.- Do not lower
tooljet.resources.maxMemorybelow4Gi— the first boot’s migrations run out of memory below it and the workload never becomes ready. - Claim the Super Admin account right after install — the first visitor to complete onboarding owns the instance, and the endpoint is public by default.
- Configure SMTP at the initial install — enabling it through a later upgrade does nothing.
tooljet.replicasof2or more requiresredis.enabled: true, and both the Redis data node and the Sentinel must stay at one replica.- Changing the database password is a database change first — run
ALTER ROLE, update the secret, then force-redeploy ToolJet (Rotating the Database Password). - Give each release its own database credentials secret — secret names are org-wide, so two releases pointed at one secret share a password.
- Uninstalling deletes the PostgreSQL volume set and every app, user, and ToolJet Database table in it; your prerequisite secrets are yours and survive.
- ToolJet is licensed under the AGPL — the deployed image is the LTS build and runs the free tier without a license key.