Skip to main content
Version: 0.17

Complete registry access and bundle extraction first. Commands use Bash (Git Bash on Windows).

For an SSO-only deployment, provision the license and first administrator mapping before startup using Authentication. Otherwise use the local administrator bootstrap below.

Install Enterprise with Helm

When using in-cluster PostgreSQL, install the CloudNativePG operator before the chart; see its installation instructions. External PostgreSQL does not need that operator.

The enterprise Helm chart is published as an OCI artifact in Harbor and bundles the core chart as a vendored subchart. You do not need a separate tokentimer-core install.

info

The bundle's helm/values.yaml documents the Enterprise overlay options, and helm/examples/ contains scenario starter files (see the table below).

a. Create the pull secret​

kubectl create namespace tokentimer
# Use a new private directory; enter the robot token at the Docker prompt.
mkdir -m 700 ./registry-auth
docker --config ./registry-auth login harbor.tokentimer.ch -u 'robot$tokentimer-enterprise+<company>-<your-id>'
kubectl create secret generic tokentimer-enterprise-registry \
--type=kubernetes.io/dockerconfigjson \
--from-file=.dockerconfigjson=./registry-auth/config.json \
-n tokentimer --dry-run=client -o yaml | kubectl apply -f -
# Remove this temporary credential copy after verifying the Secret.
rm ./registry-auth/config.json
rmdir ./registry-auth

The pull secret name matches the chart default (global.imagePullSecrets). If you choose a different name, override via --set tokentimer.global.imagePullSecrets[0].name=<your-name>. More detail, including GitOps-friendly manifest generation, is in Registry access.

b. Authenticate Helm to Harbor​

The Helm CLI needs Harbor credentials to fetch the chart (the pull secret from step a only covers container-image pulls by the cluster, not the chart pull by the Helm client):

helm registry login harbor.tokentimer.ch \
-u 'robot$tokentimer-enterprise+<company>-<your-id>'
# Enter the robot token at the password prompt.

c. Create the license secret (optional)​

You can supply the license JWT via TT_LICENSE_KEY in values, via the dashboard after boot, and/or via a file mounted from a Kubernetes Secret. The chart treats the license volume as optional when no Secret exists.

File-based install:

read -r -p 'License file path: ' ENTERPRISE_LICENSE_FILE
kubectl create secret generic tokentimer-license \
--from-file=license.key="$ENTERPRISE_LICENSE_FILE" \
-n tokentimer

If you rely on env or UI only, skip this step and omit --set license.existingSecret=... on install (or set license.existingSecret to "" in values if you overrode it).

d. Pick a starter values file and customize​

cp helm/examples/values-external-db.yaml ./my-values.yaml
$EDITOR my-values.yaml

Set public URLs before SSO or production use. Chart defaults leave localhost origins in place; if you skip this step, Manage SSO providers will show redirect URIs such as http://localhost:4000/auth/oidc/<slug>/callback.

In my-values.yaml, under the core subchart key tokentimer.config (same names as Compose APP_URL / API_URL):

tokentimer:
config:
# Dashboard origin (maps to APP_URL): links in email, where users open the UI
baseUrl: https://tokentimer.your-domain.com
# API origin (maps to API_URL): must be the URL browsers and your IdP use to reach the API
apiUrl: https://tokentimer.your-domain.com

Set tokentimer.ingress.hosts and tokentimer.ingress.tls to the same public hostname, and supply the referenced TLS Secret (or configure your certificate issuer to create it).

Use the same host when ingress terminates TLS on one hostname for both UI and API. Use separate hosts if you split them (for example baseUrl: https://app.example.com, apiUrl: https://api.example.com). A SESSION_COOKIE_DOMAIN override is optional; keep the default host-only cookie unless your deployment requires a shared cookie domain. Do not use in-cluster DNS names (tokentimer-api, pod IPs) here. See the Canonical URLs section of the Configuration reference.

SSO callback paths default to ${apiUrl}/auth/oidc/<slug>/callback and ${apiUrl}/auth/saml/<slug>/callback (slug from your provider row). If the API sits behind an ingress or reverse proxy, set trustProxyHops (top-level chart value, maps to TRUST_PROXY_HOPS) so session cookies and redirects respect X-Forwarded-* headers.

e. Install​

Use Helm 3.14+ to install straight from the OCI registry; no intermediate helm pull is needed. See Registry access for how to list published chart versions and pick <chart-version>.

read -r -p 'Enterprise chart version: ' ENTERPRISE_VERSION
helm install tokentimer oci://harbor.tokentimer.ch/tokentimer-enterprise/charts/tokentimer-enterprise \
--version "$ENTERPRISE_VERSION" \
-n tokentimer \
-f my-values.yaml \
--set license.existingSecret=tokentimer-license \
--set tokentimer.config.adminEmail=admin@your-company.com

If you are not using a license Secret, drop license.existingSecret and set TT_LICENSE_KEY under tokentimer.api.env (or paste the license in the UI after install).

info

For air-gapped clusters, change-review workflows, or inspecting every chart value, pull the chart locally first with helm pull oci://harbor.tokentimer.ch/tokentimer-enterprise/charts/tokentimer-enterprise --version <chart-version>, then install from the resulting .tgz. The full schema comes from helm show values ./tokentimer-enterprise-<chart-version>.tgz; the bundle's helm/values.yaml and example files alone are not enough for that. See Registry access.

envFrom and license volume names are derived from the Helm release name (<release>-enterprise-env, and so on). See helm/README.md in the bundle (section: Enterprise env wiring).

f. Verify​

kubectl get pods -n tokentimer -w

You should see: API and dashboard pods become Ready, migrations complete successfully, and worker CronJobs exist. Workers run as Jobs on their schedules; they are not permanent pods. Check with kubectl get jobs,cronjobs -n tokentimer.

Then open the dashboard at your ingress URL (tokentimer.config.baseUrl). If you have no ingress yet:

kubectl port-forward -n tokentimer svc/tokentimer-dashboard 8080:80 &

Open http://localhost:8080 to inspect the UI. Use the configured HTTPS dashboard URL for your first sign-in; a dashboard-only port-forward does not configure the API origin or secure session cookies. Retrieve the administrator password from the install Secret if Helm generated it (see helm/README.md). Confirm System Settings → License and that import providers match your entitlements.

Optional API smoke check (does not validate the license; use /health only):

kubectl port-forward -n tokentimer svc/tokentimer-api 4000:4000 &
curl http://localhost:4000/health

Scenario values files​

The bundle ships starter values files under helm/examples/:

FileUse case
values-minimal.yamlSingle-node CNPG, no ingress
values-external-db.yamlExternal PostgreSQL + ingress + SMTP
values-full.yamlProduction-shaped overlay: external DB, ingress, TLS, monitoring (not every chart key; pull the chart from Harbor and run helm show values on the .tgz, or helm get values -a on a live release)
values-full-test.yamlLab / Minikube with HPA, metrics, all workers
values-sso-basic-oidc.yamlSingle OIDC provider bootstrap
values-sso-basic-saml.yamlSingle SAML provider bootstrap
values-sso-multi-provider.yamlEntra OIDC + Keycloak OIDC + Keycloak SAML
values-sso-full-reference.yamlEvery supported ssoProviders[] field (parameter catalog)

Check the effective license in System Settings → License, then follow First asset and alert check. See configuration for secrets and deployment settings.