Skip to main content

Overview

Unleash is an open-source feature-flag server: toggle features on and off, roll them out gradually and run A/B tests without redeploying the applications that use them. This template deploys the free open-source edition as one stateless workload serving the admin UI and the Admin, Client and Frontend APIs on a single port, backed by a bundled PostgreSQL database that holds every flag, user and token — the postgres-highly-available template by default, or the single-instance postgres template with one flag. Because other applications gate their behaviour on it, the highly available database is the default, and the Unleash server itself scales to more replicas with a single value.
This template deploys into an existing GVC that you already have — it does not create or manage a GVC. Every workload below runs in each location of that GVC.

What Gets Created

Unleash itself has no volume set — all of its state lives in the database. The admin login, the database credentials and the optional API-token seed are prerequisite secrets you create yourself; the chart references them by name and never creates, modifies or deletes them.

Prerequisites

Two secrets must exist before you install, and a third is optional. They hold credentials, so they are prerequisite secrets rather than values — a value would sit in plaintext in the Helm release for the life of the install. Secrets are org-level, so no --gvc flag is involved.
1

Create the admin login secret (required)

A dictionary secret holding exactly the keys username and password. It seeds the initial admin account, whose login form sits on the public endpoint, so it is a prerequisite secret rather than a Helm value:
Set admin.secretName to this name. Read the values back later with cpln secret reveal ADMIN_SECRET_NAME -o yaml — the -o yaml is required; a bare reveal prints only a summary table.
2

Create the API-token seed secret (optional)

Skip this step to create SDK tokens in the admin UI after install instead. Otherwise create a dictionary secret holding exactly the keys backend and frontend, each a full Unleash token string in the format <project>:<environment>.<secret>. The open-source edition ships the default project and the development and production environments:
Set apiTokens.secretName to this name. Leaving it empty (the default) turns seeding off entirely.
3

Create the database credentials secret (required)

A dictionary secret holding exactly the keys username, password and database. The bundled PostgreSQL initializes with these values and Unleash connects with them:
Set its name in the key of the database mode you use: postgresHA.config.credentialsSecretName (HA, the default) or postgres.config.credentialsSecretName (single-instance). PostgreSQL reads the secret only when its data is first initialized; to change the password later, change it in the database first, then update the secret and force a redeployment of the Unleash workload.
A missing prerequisite secret wedges the install rather than failing it. cpln helm install reports success and every resource is created, but the Unleash container never starts — so cpln logs returns zero lines. The only place the missing secret is named is status.versions[].message:
The message reads The secret <name> no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. It is get-deployments — plain cpln workload get has no versions key. Create the missing secret and the deployment recovers on its own after several minutes, or run cpln workload force-redeployment RELEASE_NAME-unleash --gvc GVC_NAME to skip the wait.
Optional database backups need a bucket and access setup on AWS S3, Google Cloud Storage or an S3-compatible server, and S3-compatible servers additionally need a dictionary secret with the bucket keys — see Backing Up.

Installation

Once the admin and database credentials secrets exist, install the template into your GVC, naming them:
Add --set apiTokens.secretName=API_TOKENS_SECRET_NAME if you created the optional token seed. If you run more than one release of this template in the same org, create a separate database credentials secret for each — see Database.

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Unleash Instance

resources.maxCpu and resources.maxMemory are the container limits; resources.minCpu and resources.minMemory are the reservation. replicas sets a fixed replica count behind the load balancer — the server holds no state of its own, so 2 or more keeps flags served through a rolling restart or the loss of one replica. Unleash’s version check against the upstream service is disabled by the template.

Admin Account and API Tokens

  • admin.secretName names the required dictionary secret from Prerequisites, with keys username and password. Unleash creates the admin account from it on first boot only; the account then lives in the database. Editing the secret later changes nothing, and an upgrade never resets the password — change it in the admin UI.
  • apiTokens.secretName names the optional dictionary secret with keys backend and frontend. When set, both tokens are seeded on first boot only; when empty, nothing is seeded and the workload references no extra secret. Create or revoke tokens later in the admin UI.

Access

Public access is on by default because SDKs running in browsers and in applications outside the GVC call /api/frontend and /api/client directly. Every surface is authenticated — the UI and Admin API by login, the Client and Frontend APIs by tokens. Set publicAccess.enabled: false for an internal-only instance; in-GVC callers still reach it per internalAccess, and you reach the UI through a tunnel (see Connecting). A firewall change can take a few minutes to take effect, so re-test rather than trusting the first response. The URL Unleash embeds in password-reset and invite links is derived at container start: the canonical endpoint when public, the internal RELEASE_NAME-unleash.GVC_NAME.cpln.local:4242 address when not.

Database

Exactly one of the two database modes must be enabled — the chart enforces this at render and refuses to install otherwise. Unleash is wired to the active database automatically: the HAProxy leader endpoint in HA mode, or the single instance directly.
In both modes the database credentials come from your prerequisite dictionary secret, named by postgresHA.config.credentialsSecretName or postgres.config.credentialsSecretName (whichever database is enabled); the database initializes from it and Unleash connects with it. In HA mode the proxy must stay enabled — that endpoint is Unleash’s stable database address, and the chart refuses to render with postgresHA.proxy.enabled: false. Secret names are org-wide, so if you run more than one release of this template in the same org, create a separate database credentials secret for each and point each release’s credentialsSecretName at its own. Everything else the bundled databases can do — volume autoscaling, PgBouncer pooling, etcd tuning — is documented on the postgres-highly-available and postgres pages and is set under the same postgresHA.* / postgres.* prefixes. Their backup settings are covered under Backing Up.

Connecting

Read the public address from status.canonicalEndpoint, then confirm the server answers — /health returns HTTP 200 once Unleash has finished its database migrations:
With publicAccess.enabled: false there is no canonical endpoint. Open a tunnel to the UI instead and browse to http://localhost:4242:

First Run

Unleash has no setup wizard: the admin account is created from your admin secret on first boot. A fresh install in HA mode takes several minutes to become ready while the database cluster forms; the start script waits until the database accepts queries before Unleash runs its migrations.
1

Wait for the workload to report ready

2

Sign in

Open the canonical endpoint (or http://localhost:4242 through the tunnel) and sign in with the username and password from your admin secret. Change the password in the UI if you wish — that is the only place it changes from now on.
3

Create an SDK token

If you did not seed tokens through apiTokens.secretName, go to Admin → API access and create one: choose Backend for a server-side SDK or Frontend for a browser or mobile SDK, then the project and environment it applies to.

API Tokens

SDKs authenticate with an API token in the Authorization header, and the two token types are not interchangeable:
  • Backend tokens authenticate server-side SDKs against /api/client. Treat them like passwords.
  • Frontend tokens authenticate browser and mobile SDKs against /api/frontend. They are designed to be embedded in client code.
A token string names its project and environment (<project>:<environment>.<secret>), so a 401 or 403 from an SDK API usually means the wrong token type for the endpoint or the wrong environment in the token.

Operations

Backing Up

Database backups are optional and disabled by default. They cover the database — every flag, strategy, segment, user and token in your Unleash instance. Enable them on whichever database is active and complete the storage setup for your provider before installing or upgrading with them on.
In HA mode postgresHA.backup.mode selects logical (a scheduled dump run by the RELEASE_NAME-postgres-ha-backup cron workload through the HAProxy endpoint) or wal-g (continuous WAL archiving from the database workload itself, with no separate backup workload). The single-instance database takes scheduled logical dumps only, through RELEASE_NAME-postgres-backup. Both come from the bundled postgres-highly-available and postgres templates. The steps below name the keys under postgresHA.backup.*; in single-instance mode set the same keys under postgres.backup.*.
1

Create a bucket

Create an S3 bucket. Set postgresHA.backup.aws.bucket and postgresHA.backup.aws.region to match.
2

Set up a Cloud Account

If you do not have one, create a Cloud Account for the AWS account holding the bucket. Set postgresHA.backup.aws.cloudAccountName to its name.
3

Create a bucket-scoped IAM policy

Create an IAM policy with the JSON below (replace YOUR_BUCKET), then set postgresHA.backup.aws.policyName to the policy’s name:
A database backup does not cover your prerequisite secrets; keep a copy of the admin login somewhere safe. The database volume sets also take a final snapshot when they are deleted, kept for seven days.

Restoring a Backup

No restore path has been rehearsed against this template. The outline below follows the bundled database templates’ own restore procedures and this chart’s configuration; rehearse it against a scratch release before you depend on it. Restoring from a volume set snapshot is likewise unverified here.
A restore goes into the database, not into Unleash: everything that makes up your instance lives there, so restoring it brings back flags, strategies, users and tokens together. A logical backup is a gzip-compressed SQL file (.sql.gz under your prefix), replayed with psql from a client that can reach both the bucket and the database — a workload inside the GVC, or your own machine with a tunnel open. The Unleash container is not that client. In HA mode go through the HAProxy endpoint so the writes land on the leader:
Use RELEASE_NAME-postgres as the workload name in single-instance mode. The full per-provider replay commands, and the WAL-G outline for HA mode — which ends in a manual volume-set swap this chart does not expose — are on the postgres-highly-available and postgres pages. Restore into an empty database and keep Unleash from connecting until the replay has finished. Because the restored database already holds an admin account, the admin secret is not applied again — sign in with the account from the dump.

Upgrading from 1.0.x

Two changes landed between 1.0.0 and 1.1.0; apply both when upgrading from 1.0.0. 1.0.1 — etcd compaction. Version 1.0.0 did not compact the etcd cluster inside the bundled highly available database, so etcd’s backend grows with time alone and eventually goes read-only when it reaches its quota — taking PostgreSQL failover with it. Only installs running the HA database are affected (postgresHA.enabled, the default). See etcd History Compaction for the mechanism and symptoms. Upgrading to 1.0.1 or later turns compaction on; that stops further growth but cannot shrink a backend that has already grown, and a cluster that has already raised a NOSPACE alarm needs operator recovery rather than an upgrade. 1.1.0 — the admin login became a prerequisite secret. Earlier versions shipped admin.username and a working admin.password as values — a published default guarding a login form on the public endpoint. An upgrade that still carries either key is rejected at render, before anything is applied, with a message naming its replacement; there is no compatibility fallback. Version 1.1.0 also made the start script wait for the database before Unleash runs its migrations.
1

Create the admin login secret

Follow Prerequisites. Its contents only matter to a fresh install — the account already exists in your database and is only created on first boot, so your existing admin password does not change on upgrade. An existing apiTokens.secretName secret stays exactly as it is.
2

Drop the removed keys and upgrade

Remove admin.username and admin.password from your values and set admin.secretName. The Unleash replicas restart; flags, users and tokens are in the database and are untouched.
3

Change the admin password in the UI

If the install was still using the published 1.0.x default password (change-me-unleash-admin), treat it as compromised and change it now in the Unleash UI — the secret cannot change an existing account. Every later migration note below also applies.

Upgrading from 1.1.0

Version 1.2.0 adopted the postgres 3.4.1 template, which stopped taking database credentials as values. In single-instance mode three keys were removed: Put the values your single-instance database was initialized with into the database credentials secret under Prerequisites, set postgres.config.credentialsSecretName to its name, and remove the three keys. 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). If you back up to MinIO, create the dictionary secret described under Backing Up and set postgres.backup.minio.credentialsSecretName. The HA path is unchanged by this step.

Upgrading from 1.2.x

Version 1.3.0 adopted the postgres-highly-available 2.5.0 template, which made the same change on the HA path, and 1.3.1 did the same for its MinIO backup keys. The HA database credentials now come from the database credentials secret named by postgresHA.config.credentialsSecretName. Put the three credential values unchanged into the database credentials secret under Prerequisites — the running cluster was initialized with them — set postgresHA.config.credentialsSecretName to its name, and delete the postgresHA.postgres block entirely. A values file that still carries the old block stops the upgrade at render:
If you back up the HA database to an S3-compatible server, create the credentials secret described under Backing Up with the same access key and secret key, set postgresHA.backup.minio.credentialsSecretName, and remove the two old keys; if you are already on 1.3.0, that MinIO change is the only part of this step that applies.

Upgrading from 1.3.x

Version 1.4.0 renamed the Unleash container’s resource limits: a block that exposes both a reservation and a limit now names the limit maxCpu / maxMemory, so it is no longer ambiguous which number is the ceiling. Nothing else changed. An upgrade that still carries either old key is refused at render with unleash: resources.cpu was RENAMED to resources.maxCpu (or the memory equivalent); rename the two keys and upgrade. resources.minCpu and resources.minMemory keep their names, and the backup resources blocks, which expose only a limit, keep cpu and memory.

Upgrading from 1.4.0

Version 1.5.0 removed postgres.credentials: the database credentials are now a prerequisite secret, the same one the database templates require on their own. Carrying the old key forward fails the render. 1.4.0 created the database secret itself, so this upgrade deletes it. Before upgrading, create a secret under a new name holding the values your database was initialized with — not new ones, or Unleash loses its database connection:
Then upgrade with postgresHA.config.credentialsSecretName (HA mode) or postgres.config.credentialsSecretName (single-instance mode) set to that name, and postgres.credentials removed. Your current values are in postgres.credentials of the 1.4.0 release, and also in the old secret (cpln secret reveal my-unleash-db-credentials -o yaml, or the name your release set in credentialsSecretName) until the upgrade deletes it. The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Unleash can briefly lose its database; it reconnects by itself. The new version of a workload can also wait for several minutes, with get-deployments reporting that it is not allowed to reveal the secret, while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself.

Upgrading from 1.5.0 or earlier

1.5.1 moves the HA database (postgresHA) to controlplanecorporation/patroni-postgres:0.8, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Unleash itself restarts without a gap: the new replica serves before the old one stops. Upgrade in a quiet window. If you pinned postgresHA.image in your values, set it to the 0.8 tag: tags 0.1 to 0.7 are refused at render. Unleash does not use the vector extension; if you created it yourself in a database, \dx keeps reporting the old version until you run ALTER EXTENSION vector UPDATE; there, which only updates that record. Single-instance mode (postgres) is unchanged.

Rotating the Database Password

PostgreSQL reads the database credentials secret only when its data is first initialized, and a running workload keeps the values it started with. In single-instance mode, change the password in the database first (ALTER ROLE DB_USERNAME PASSWORD 'NEW_PASSWORD';), then update the secret with cpln secret edit SECRET_NAME and force a redeployment of the Unleash workload:

Rotating the Database Password in HA Mode

The HA database (postgresHA) needs its own order. The replication role repl shares the password, and a member that restarts with the old password can be promoted to leader, which splits the cluster. Move the leader to member -0 first, so it restarts last, after every other member already has the new password. pgx runs a command in one member (LOCATION is your GVC’s location, DB_USERNAME the secret’s username):
Then force-redeploy RELEASE_NAME-unleash, which keeps the old password until it restarts. The database drops connections briefly at each switchover, and the app cannot open new connections from the ALTER ROLE until its own redeploy finishes, so rotate in a quiet window. If a member stays starting, or running without streaming for several minutes, re-copy it from the leader. This copies the whole database, so it costs network traffic in proportion to its size:

Scaling and Availability

  • The Unleash server is stateless — set replicas to 2 or more so flags keep being served through a rolling restart or the loss of a replica. Every Helm upgrade rolls the Unleash replicas.
  • Database replicas are set with postgresHA.replicas; the single-instance database must stay at one replica.
  • The first helm upgrade after an install can restart the bundled database even when no database value changed, so expect a short interruption on that first upgrade.
  • Seeded secrets apply on first boot only. Editing the admin or API-token secret later does not change the account or the tokens; manage both in the admin UI.
  • Confirm an upgrade is live from the deployment, not from the Helm output — cpln workload get-deployments RELEASE_NAME-unleash --gvc GVC_NAME -o yaml.
  • Uninstall deletes every volume set the chart created — the database and, in HA mode, the consensus store — so the data does not survive a reinstall. The GVC is yours and is left alone, and the prerequisite secrets you created survive. Enable backups if the data matters.

Troubleshooting

Symptom: cpln helm install succeeded, but RELEASE_NAME-unleash shows no running containers and cpln logs returns nothing.Cause: A prerequisite secret named in your values does not exist — the admin secret, the database credentials secret, or the API-token secret when apiTokens.secretName is set. The deployment pauses on the unresolved reference.Fix: Read the message naming the secret, then create it:
The message reads The secret <name> no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. Once the secret exists the deployment recovers on its own, or run cpln workload force-redeployment RELEASE_NAME-unleash --gvc GVC_NAME to skip the wait.
Symptom: Several minutes after a fresh install, RELEASE_NAME-unleash is not ready yet and its logs contain Failed to migrate db.Cause: Unleash cannot run its schema migrations until the bundled database cluster has formed and the HAProxy endpoint routes to a leader. Transient migration errors while the cluster starts are expected and self-correcting, at any replica count.Fix: Wait, then re-check cpln workload get-deployments RELEASE_NAME-unleash --gvc GVC_NAME -o yaml. Confirm the database tier is ready first with cpln workload get-deployments RELEASE_NAME-postgres-ha --gvc GVC_NAME -o yaml. Read the errors with a server-side filter:
Symptom: An SDK cannot fetch flags and the API answers 401 or 403.Cause: The token type does not match the endpoint — a frontend token sent to /api/client, or a backend token sent to /api/frontend — or the environment in the token string is not the one you meant.Fix: Use a backend token for server-side SDKs and a frontend token for browser and mobile SDKs, and create a new one in Admin → API access if needed. See API Tokens.
Symptom: The install stops with unleash: enable exactly one database — set either postgresHA.enabled or postgres.enabled to true, not both, or the variant naming postgresHA.enabled (production) or postgres.enabled (dev/lightweight).Cause: Both postgresHA.enabled and postgres.enabled are true, or both are false.Fix: Enable exactly one — see Database. To use the single-instance database, set postgresHA.enabled: false together with postgres.enabled: true.
Symptom: helm upgrade stops at render with admin.password was REMOVED in 1.1.0, config.username was REMOVED in postgres 3.4.0, the postgres block was REMOVED in 2.5.0, backup.minio.accessKey and backup.minio.secretKey were REMOVED, resources.cpu was RENAMED to resources.maxCpu, or postgres.credentials was REMOVED.Cause: Your values still carry a key that moved in template versions 1.1.0, 1.2.0, 1.3.0, 1.3.1, 1.4.0 or 1.5.0. The existing release is left untouched and running.Fix: Follow the matching migration note above — Upgrading from 1.0.x, Upgrading from 1.1.0, Upgrading from 1.2.x, Upgrading from 1.3.x or Upgrading from 1.4.0 — keeping the credentials the database already uses in your database credentials secret.

Important Notes

  • Create the admin secret and the database credentials secret before installing. A missing prerequisite secret does not fail the install — the workload waits on it with zero log lines.
  • Rotating the database password needs a forced redeployment — a running workload keeps the values it started with, and the database keeps its password until you change it there; in HA mode a leader switchover comes first. See Rotating the Database Password.
  • The admin secret and the API-token seed apply on first boot only. Change the password and manage tokens in the admin UI; editing the secrets later changes nothing, and an upgrade never resets your password.
  • Backend tokens must stay secret (server-side SDKs, /api/client); frontend tokens are safe to embed in browsers (/api/frontend).
  • Give each release its own database credentials secret — secret names are org-wide.
  • The free edition ships two environments (development, production); SSO, role-based access control, multiple projects, change requests and audit logs need an Unleash Enterprise license and are not available in this template.
  • Uninstall deletes the database volume sets — all flags, users and tokens. Enable backups if the data matters; the prerequisite secrets you created survive and must be deleted manually.

External References

Unleash Documentation

Official Unleash documentation

Configuring Unleash

Environment variable configuration reference

API Tokens and Client Keys

Token types, formats, and how SDKs authenticate

SDK Overview

Official backend and frontend SDKs

Unleash Template

View the source files, default values, and chart definition