Skip to main content

Overview

Umami is a privacy-first, cookieless web and product analytics platform — a self-hosted, MIT-licensed alternative to Google Analytics. This template deploys the stateless Umami v3 app tier backed by a bundled PostgreSQL store, serving the analytics dashboard and the tracking endpoint on the same port. You embed a small tracking script on your site; visitor events are posted back to the same workload and stored in PostgreSQL, with no cookies and no personal data collected. The install starts private: Umami seeds a hardcoded admin / umami account that no setting can override, so publicAccess.enabled defaults to false and you publish the install only after changing that password. Tracking collects nothing until you do — follow First Run.
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

Umami itself has no volume set — every user, website, session and event lives in PostgreSQL. The app secret is a prerequisite secret you create yourself; the chart references it by name and never creates, modifies or deletes it.

Prerequisites

One opaque secret must exist before you install. Secrets are org-level, so no --gvc flag is involved.
1

Create the app secret

The app secret signs Umami’s auth tokens and sessions — anyone holding it can forge a login — so it is never a Helm value and never lands in the release. Generate a random value and store it as the secret’s payload:
Keep it for the life of the install: changing it logs every user out. Set app.appSecretName to this name.
2

Choose the database password

The bundled database’s credentials are internal plumbing: this chart writes postgres.credentials.username, postgres.credentials.password and postgres.credentials.database into a dictionary secret it creates, and both Umami and the database read it. Nothing to create — but the password ships as the placeholder change-me-umami-db, so set postgres.credentials.password to a value of your own before installing. This applies in both database modes.
A missing app secret wedges the install rather than failing it. cpln helm install reports success and every resource is created, but the Umami 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 within several minutes, or run cpln workload force-redeployment RELEASE_NAME-umami --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 app secret exists, install the template into your GVC, naming the secret and replacing the database password placeholder:
Keep these settings in a values file (--values) rather than --set if you do not want the database password in your shell history — and because every later upgrade must pass them again. If you run more than one release of this template in the same org, also give each its own postgres.config.credentialsSecretName — see Backing Store.

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

Application

Replicas are independent — they share only the database and the app secret, so a session opened against one replica is honored by the others.

Tracker

Custom paths are aliases, not replacements: the default /script.js and /api/send keep working. They help because your site loads a path ad blockers do not recognise. The custom collect path is baked into the script Umami serves, so the snippet you embed picks it up automatically.

Backing Store

Enable exactly one of the two stores — the chart refuses to render with both or neither. Umami is wired to whichever is active.

Choosing a Database Mode

To use HA mode on a new install, set postgres.enabled: false and postgresHA.enabled: true. The credentials still come from postgres.credentials.* in both modes. Switching an existing release between modes does not move data — the other store starts empty. Secret names are org-wide, so if you run more than one release of this template in the same org, give each its own credentials secret name — postgres.config.credentialsSecretName, or postgresHA.config.credentialsSecretName in HA mode. A second release left on the default name is refused at install and creates nothing; the first release is unaffected. Database backups are configured under postgres.backup / postgresHA.backup — see Backing Up.

Access

Tracking collects nothing while publicAccess.enabled is false — browsers on the sites you track must reach the tracking script and the collect endpoint. Turn it on once the admin password is changed. An access change takes a few minutes to take effect, so re-test rather than trusting the first response.

Connecting

CANONICAL_ENDPOINT is the host of status.canonicalEndpoint. Open a tunnel to the dashboard from your machine — this works whether or not public access is on:
Then confirm the app answers with curl -sS http://localhost:3000/api/heartbeat. The heartbeat does not touch the database, so a 200 there proves only that the app tier is up; loading the dashboard is the check that the database is reachable too.

First Run

Umami’s bootstrap admin is a hardcoded admin / umami, seeded by its first database migration and published in Umami’s own documentation. The install therefore starts private, and you publish it once the password is changed.
1

Install with public access off

Install as shown in Installation, leaving publicAccess.enabled at its default false. Wait until the workload reports ready:
2

Open the dashboard through a tunnel

cpln port-forward is a top-level command, not a subcommand of cpln workload. Open http://localhost:3000/login in a browser and sign in as admin / umami.
3

Change the admin password

In the dashboard, open Settings → Profile and change the password. From then on the old password is rejected.
4

Publish the dashboard and tracking endpoint

Upgrade the release with publicAccess.enabled=true, passing the same app secret name and database password you installed with (or the same values file):
Upgrading through the marketplace UI is the alternative. Allow a few minutes for public access to take effect, then read the endpoint with cpln workload get RELEASE_NAME-umami --gvc GVC_NAME -o yaml.
5

Add your website and embed the tracker

In the dashboard, add a website, then paste the generated <script> tag into the HTML of your site. It loads the tracking script from the public address and posts events to the collect endpoint.
The publishing upgrade is the first upgrade after the install, and it can restart the bundled database even though no database value changed. Expect Umami to be briefly unreachable while the database comes back; this is not a failed upgrade — do not roll back. Confirm recovery by loading the dashboard rather than by /api/heartbeat, which answers even while the database is down.

Operations

Backing Up

Database backups are optional and disabled by default. They cover everything that makes up your Umami instance — users, websites, sessions and events. They are a pass-through to the bundled database template, which runs the backup as a scheduled job; enable them on whichever store is active and complete the storage setup for your provider before installing or upgrading with them on. Single-instance mode:
HA mode — the same providers, plus a choice of backup mode:
1

Create a bucket

Create an S3 bucket. Set backup.aws.bucket and backup.aws.region on the active store to match.
2

Set up a cloud account

If you do not have one, create a cloud account for your AWS account. Set backup.aws.cloudAccountName to its name.
3

Create a bucket-scoped IAM policy

Create an AWS IAM policy scoped to your bucket, then set backup.aws.policyName to its name:

Restoring a Backup

No restore path has been rehearsed against this template. A restore goes into the database, not into Umami, and follows the bundled database template — rehearse it against a scratch release before you depend on it. Restoring from a volume set snapshot is likewise unverified here.
Use the procedure on the postgres page in single-instance mode, or the postgres-highly-available page in HA mode, with these Umami-specific values:
  • The database workload is RELEASE_NAME-postgres (single-instance) or RELEASE_NAME-postgres-ha-proxy (HA mode — always go through the leader endpoint).
  • The username, password and database name are the keys of the credentials secret: cpln secret reveal DB_CREDENTIALS_SECRET_NAME -o yaml.
  • The Umami container has neither psql nor a cloud CLI, so run the restore from a client that can reach both the bucket and the database — your own machine with a cpln port-forward to the database workload open, for example.
  • Restore into an empty database and keep Umami from writing until the replay has finished; replaying into a database Umami has already migrated collides with the existing schema.
The restored data carries its own users, so after a restore you sign in with the passwords stored in the backup, not admin / umami.

Upgrading From 1.0.0

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 goes read-only once it reaches its quota — taking PostgreSQL failover with it. Only installs running the HA database are affected (postgresHA.enabled). 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. See etcd History Compaction.

Upgrading From 1.0.1

Version 1.1.0 is a security release that renames three values. Carrying a 1.0.1 values file forward fails at render with a message naming the replacement, so nothing silently reverts to a default: publicAccess.enabled also changed its default to false. An upgrade that does not set it explicitly makes the install private and stops data collection — pass publicAccess.enabled=true once the admin password is changed.

Upgrading From 1.1.0

Version 1.2.0 moved the single-instance database credentials. Carrying the old keys forward fails at render: Move the three credential values unchanged — the database was initialised with them. The error message comes from the bundled database (config.username was REMOVED in postgres 3.4.0) and tells you to create a credentials secret yourself; ignore that part — this template creates it from postgres.credentials.*. The MinIO keys, by contrast, are a real prerequisite secret: create it as shown in Backing Up.

Upgrading From 1.2.0

Version 1.3.0 moved the HA database credentials onto the same chart-created secret as single-instance mode. Carrying the old block forward fails at render with the postgres block was REMOVED in 2.5.0. The three username, password and database values that sat in a postgres block under postgresHA now come from postgres.credentials.username, postgres.credentials.password and postgres.credentials.database, and this chart writes them into the secret named by postgresHA.config.credentialsSecretName. Delete that block from your values and set postgres.credentials.* to the same values it held — the HA database was initialised with them. Do not create the credentials secret yourself. This path has not been rehearsed on an existing HA install; take a backup before upgrading. Single-instance installs need no action.

Upgrading From 1.3.0

Version 1.3.1 moved the HA database’s MinIO backup keys into a prerequisite secret. With HA-mode MinIO backups on, the old accessKey and secretKey values under postgresHA.backup.minio now fail at render: create a dictionary secret holding accessKey and secretKey as shown in Backing Up and set postgresHA.backup.minio.credentialsSecretName to its name. No other install needs action.

Scaling and Availability

  • The app tier scales with replicas. It is stateless — replicas share only the database and the app secret — so 2 or more gives an always-on tier whose rolling restarts cycle one replica at a time.
  • The database is the availability limit. In single-instance mode a database restart makes the dashboard and collection briefly unavailable; set postgresHA.enabled: true on a new install for automatic failover.
  • The first helm upgrade after an install can restart the bundled database even when no database value changed.
  • Uninstall deletes every volume set the chart created, so all analytics data is lost and does not survive a reinstall. The GVC is yours and is left alone, and your app secret survives. Enable backups if the data matters.

Troubleshooting

Symptom: cpln helm install succeeded, but RELEASE_NAME-umami shows no containers and cpln logs returns nothing.Cause: The secret named by app.appSecretName does not exist. The deployment pauses on the unresolved reference.Fix: Read the message naming the secret, then create it as shown in Prerequisites:
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 within several minutes, or run cpln workload force-redeployment RELEASE_NAME-umami --gvc GVC_NAME to skip the wait.
Symptom: The website is added and the tracker is embedded, but no pageviews arrive.Cause: Most often publicAccess.enabled is still false, so browsers cannot reach the tracking script or the collect endpoint — or the embedded script points at an address other than the public canonical endpoint. Ad blockers also block the default /script.js and /api/send.Fix: Set publicAccess.enabled=true (see First Run), confirm the <script> tag uses the public address, and set tracker.scriptName / tracker.collectEndpoint to custom paths to reduce ad-blocker interception.
Symptom: The install stops with umami: enable exactly one backing store — set either postgres.enabled or postgresHA.enabled to true, not both, or the variant naming postgres.enabled (default) or postgresHA.enabled (durable HA).Cause: Both postgres.enabled and postgresHA.enabled are true, or both are false.Fix: Enable exactly one — see Choosing a Database Mode. For HA mode set postgres.enabled: false together with postgresHA.enabled: true.
Symptom: Installing a second release of this template in the same org fails with cannot be updated because it is being managed by a different release, naming the database credentials secret, and creates nothing.Cause: Secret names are org-wide, and both releases are trying to create the same credentials secret (default my-umami-db-credentials). The first release owns it.Fix: Give the new release its own postgres.config.credentialsSecretName (or postgresHA.config.credentialsSecretName in HA mode) and install again. The first release is unaffected.
Symptom: All dashboard sessions end at once and everyone has to sign in again.Cause: The payload of the secret named by app.appSecretName changed, or app.appSecretName now points at a different secret. Existing tokens were signed with the old value.Fix: Nothing is lost — users sign in again. To avoid it, keep the app secret stable for the life of the install.
Symptom: helm upgrade stops at render with app.appSecret was removed in 1.1.0, resources.cpu was renamed to resources.maxCpu, config.username was REMOVED in postgres 3.4.0, the postgres block was REMOVED in 2.5.0, or backup.minio.accessKey and backup.minio.secretKey were REMOVED.Cause: Your values still carry a key that moved in template versions 1.1.0 to 1.3.1. The existing release is left untouched and running.Fix: Follow the matching migration note above — Upgrading From 1.0.1, Upgrading From 1.1.0, Upgrading From 1.2.0 or Upgrading From 1.3.0 — keeping the credentials the database already uses. Do not create a database credentials secret yourself; this template creates it.

Important Notes

  • Create the app secret before installing, and change postgres.credentials.password from its change-me placeholder. A missing app secret does not fail the install — the workload waits on it with no logs.
  • Change the hardcoded admin / umami password before turning public access on — follow First Run in order.
  • Tracking collects nothing until publicAccess.enabled is true, and the tracking script must be loaded from the public address.
  • Keep the app secret stable — changing it logs every user out. It is not owned by the release: it survives helm uninstall and must be deleted manually.
  • Pass the same app secret name and database password on every upgrade — a values file is the simplest way.
  • Give each release its own credentialsSecretName — secret names are org-wide, and a second release on the default name is refused at install.
  • Uninstall deletes the database volume sets — enable backups if the analytics data matters.

External References

Umami Documentation

Official Umami documentation

Tracker Configuration

Configure the tracking script and its options

Collect API

How events are sent to the collect endpoint

Environment Variables

Umami environment variables reference

Umami Template

View the source files, default values, and chart definition