Configuring Tines with Helm
Configure Tines by creating a local values.yaml file that overrides the Helm chart defaults. This guide covers registry access, tenant setup, database and Redis connections, email, storage, networking, and optional components.
Before you begin, add the Tines Helm repository.
Prepare your values file
Inspect the defaults for the chart version you plan to install. Replace <chart-version> with your selected version:
helm show values tines/tines --version <chart-version>Create values.yaml with the overrides you need. The examples below are separate configuration fragments. Combine settings under a single top-level key, such as tinesApp, rather than repeating that key in the file.
Configuration options vary by chart version. Check that your selected version supports each option before using it.
Use existing Kubernetes Secrets
The chart can read sensitive values from Kubernetes Secrets you manage. Create these Secrets in the installation namespace before installing or upgrading Tines. The sections below show how to reference them for registry access, application settings, database credentials, and nginx TLS.
Note: When switching an existing installation to these references, copy any chart-created Secret to a different name first. The chart rejects
container-registry-secret,db-secret, andnginx-ssl-certsasexistingSecretnames because Helm removes those resources when the chart stops creating them.
Registry credentials
Use credentials for the registry that hosts your chart's images. See Accessing the OCI registry or Accessing the Docker registry for authentication instructions.
For images hosted at oci.tines.com:
tinesContainerRegistryCredentials:
registry: oci.tines.com
username: "<your-oci-username>"
password: "<your-oci-password>"
email: "<your-email>"The chart uses these values to create an image pull secret. If your chart uses registry.tines.com, set the registry and credentials to match.
To use an existing image pull Secret instead:
tinesContainerRegistryCredentials:
existingSecret: tines-registryThe Secret must have type kubernetes.io/dockerconfigjson and contain credentials for the image registry. Leave username, password, and email unset when using existingSecret; the chart rejects combining them.
If you use an internal registry mirror, update the relevant deployments.*.image settings to match the mirrored images. For OpenShift, update deployments.*.openshiftImage instead. Check the registry, repository, and tag for each image.
App secret token
Generate a random 128-character token:
openssl rand -hex 64Add the generated value to your configuration:
tinesApp:
serverConfiguration:
APP_SECRET_TOKEN: "<128-character-token>"The chart requires an app secret token. Keep the same token when upgrading an existing installation.
To read the token from a Secret instead:
tinesApp:
secretEnv:
APP_SECRET_TOKEN:
name: tines-app-secrets
key: APP_SECRET_TOKENThe Secret must contain the token at the specified key. Leave serverConfiguration.APP_SECRET_TOKEN unset when using this reference. More generally, a setting in secretEnv must not also be set in the chart's application configuration maps.
Initial tenant configuration
Set the domain, tenant name, and details for the first administrator:
tinesApp:
initialTenantConfiguration:
DOMAIN: tines.your-company.com
SEED_EMAIL: admin@your-company.com
SEED_EMAIL_PASSWORD: "<password>"
SEED_FIRST_NAME: Admin
SEED_LAST_NAME: User
TENANT_NAME: your-company-nameNote:
initialTenantConfigurationseeds the first tenant and administrator. Changing these values in a later Helm upgrade does not update the existing tenant or user.
The SEED_* fields are optional. Set the fields needed for your initial administrator rather than relying on default credentials.
Apply tenant configuration
Use tinesApp.tenantConfiguration to apply tenant settings during installation and upgrades. Enable it explicitly and create any referenced Secrets before running Helm:
tinesApp:
tenantConfiguration:
enabled: true
license:
existingSecret: tines-license
key: license
limits:
dailyStoryEvents: 250000
dailyTenantEvents: 500000
teams:
- name: Security
caseGroups:
- name: InvestigationsThis example reads the license key from a Secret, sets daily event limits, and creates a root team with a case group as a child team. The action limit is defined by the license key.
The setup job applies the supported configuration after database migration, in one database transaction. Each upgrade applies the configured values again. Teams and case groups are matched by name; removing an entry from your values file leaves the saved entry in place. Leave a setting empty to keep its current value.
You can also configure:
The primary SAML or OIDC configuration, SSO group mappings, and LDAP.
Public access for pages, MCP, and AI Agent Chat, and whether personal teams are enabled.
Login notices, direct credential access, Run Script, automatic mode, page branding, and change control.
Story allocation, AI settings, event-limit alert thresholds, action egress rules, custom certificate authorities, and sender email addresses.
Removal of the seed team, or removal or deactivation of the seed user.
Store the license, SSO certificates and client secrets, LDAP bind password, and custom certificate authorities in Secrets. For LDAP managed through tenantConfiguration.ldap, do not also set LDAP_* environment variables on the application pods.
See the chart's tenant configuration reference↗ for complete examples and required fields. Match these options to the values in your selected chart version.
Run a custom configuration script
For settings the supported tenant configuration does not cover, the setup job can run a Rails script from an existing ConfigMap or Secret:
tinesApp:
tenantConfiguration:
customScript:
existingConfigMap: customer-tenant-setup
key: configure.rbSet either existingConfigMap or existingSecret. The specified key must contain the script. The script runs after database migration and the supported tenant configuration, even if tenantConfiguration.enabled is false.
The script runs again on every upgrade, so it must be safe to repeat. If it fails, the setup job fails, but tenant settings already saved by the supported configuration remain in place. Use customScript.env for additional environment variables, including Secret and ConfigMap references; see the configuration reference↗ for its format and restrictions.
Database
Tines uses PostgreSQL for persistent data. The chart can deploy PostgreSQL in the cluster, or connect to a database you manage separately. We recommend a managed database service where possible to simplify scaling and backups.
Use the bundled database
Provide the database credentials:
tinesApp:
databaseConfiguration:
DATABASE_NAME: tines_production
DATABASE_USERNAME: tines
DATABASE_PASSWORD: "<password>"
DATABASE_POOL: 20
DATABASE_PORT: 5432Leave db.create enabled and use the database host selected by your chart version. Chart defaults can change between versions. For example, chart 44.2.4 uses PostgreSQL 18 for new installations and preserves the database connection of existing installations during upgrades.
For the bundled database on OpenShift, set PGDATA to a subdirectory so PostgreSQL can initialize it with the required permissions:
db:
PGDATA: /var/lib/postgresql/data/userdataConfigure additional PostgreSQL server settings with db.extraConfig. The bundled database defaults to max_connections: 500:
db:
extraConfig:
max_connections: 500These settings apply to the bundled PostgreSQL instances. Configure an external database through its own management tools.
Use an external database
Disable the bundled database and provide your database endpoint:
db:
create: false
tinesApp:
databaseConfiguration:
DATABASE_HOST: my-postgres.example.com
DATABASE_NAME: tines_production
DATABASE_USERNAME: tines
DATABASE_PASSWORD: "<password>"
DATABASE_POOL: 20
DATABASE_PORT: 5432For an existing PostgreSQL 14 installation, see Upgrading from PostgreSQL 14 to PostgreSQL 18 before changing the database version or host.
Read database credentials from a Secret
For either a bundled or external database, reference a Secret containing the username and password:
tinesApp:
databaseConfiguration:
existingSecret: tines-db
usernameSecretKey: POSTGRES_USER
passwordSecretKey: POSTGRES_PASSWORDRemove DATABASE_PASSWORD from your values when using this reference. DATABASE_USERNAME may remain at its default. Continue configuring the database host, name, port, and pool as needed; use databaseConfiguration.existingSecret for database credentials rather than secretEnv.
For an existing database, the Secret must contain credentials that the database already accepts. Changing the Secret does not change the PostgreSQL role or password. A new bundled database is initialized from the Secret when its data directory is empty.
Redis
Tines uses a Redis-compatible service for caching and job queues. The current chart's bundled service uses Valkey 7.2. Existing Redis image overrides remain supported. We recommend a managed service where possible to simplify scaling.
To use an external service, disable the bundled service and set the connection URL:
redis:
create: false
tinesApp:
redisConfiguration:
REDIS_URL: redis://my-redis.example.com:6379/0SMTP server
Configure an SMTP server to send invitations, notifications, monitoring emails, and emails from the Send Email action:
tinesApp:
emailConfiguration:
SMTP_SERVER: smtp.your-company.com
SMTP_DOMAIN: your-company.com
SMTP_USER_NAME: smtp-user
SMTP_PASSWORD: "<password>"
SMTP_PORT: "587"
SMTP_AUTHENTICATION: login
SMTP_ENABLE_STARTTLS_AUTO: trueAdjust the port, authentication method, and TLS settings for your SMTP server. SMTP is required to invite the first administrator by email unless you set SEED_EMAIL_PASSWORD.
All SMTP fields are optional for chart installation. For an unauthenticated relay, omit the username and password and set SMTP_AUTHENTICATION: none. Without working SMTP, email-dependent features, including invitations and password resets, cannot send email.
To read the SMTP password from a Secret:
tinesApp:
secretEnv:
SMTP_PASSWORD:
name: tines-smtp
key: SMTP_PASSWORDLeave emailConfiguration.SMTP_PASSWORD unset when using this reference.
Persistent storage
Your cluster needs a StorageClass that supports ReadWriteOnce persistent volumes.
Set the storage class for the components you deploy. Replace your-storage-class with the name of a StorageClass in your cluster:
db:
storageClassName: your-storage-class
redis:
storageClassName: your-storage-class
deployments:
pypiServer:
storageClassName: your-storage-classStorage defaults vary by chart version. Inspect the selected chart's values instead of assuming it uses your cluster's default StorageClass.
We recommend a StorageClass with a Retain reclaim policy to preserve the underlying persistent volume when its claim is deleted.
Load balancer
Choose one of the following approaches to expose Tines. Your load balancer must support WebSockets for live updates in the UI.
Use the bundled nginx proxy
The chart's nginx service exposes HTTP on port 30080 and HTTPS on port 30443 by default.
To terminate TLS at nginx, provide your certificate and private key:
nginx:
enabled: true
tinesCrt: |
-----BEGIN CERTIFICATE-----
<your-certificate>
-----END CERTIFICATE-----
tinesKey: |
-----BEGIN PRIVATE KEY-----
<your-private-key>
-----END PRIVATE KEY-----To use a certificate and private key from an existing Secret instead:
nginx:
enabled: true
existingSecret: tines-nginx-tls
certSecretKey: tls.crt
keySecretKey: tls.keyThe Secret must contain the certificate and key under the specified keys. Leave tinesCrt and tinesKey unset when using existingSecret.
Use Kubernetes Ingress
The optional Ingress routes traffic to the Tines web server on port 3000. Disable the bundled nginx proxy when using this approach:
nginx:
enabled: false
ingress:
enabled: true
className: nginx
annotations: {}
hosts:
- host: tines.your-company.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: tines-tls
hosts:
- tines.your-company.comThis example uses an nginx Ingress controller. Set className, annotations, and TLS configuration for your controller. The chart defaults include annotation examples for AWS ALB, Azure Application Gateway, and Google Cloud Load Balancing.
Use an OpenShift Route
To expose Tines with an OpenShift Route, disable nginx and configure the route:
nginx:
enabled: false
route:
enabled: true
annotations: {}
host: tines.your-company.com
path: /
tls:
termination: edge
key: |
-----BEGIN PRIVATE KEY-----
<your-private-key>
-----END PRIVATE KEY-----
certificate: |
-----BEGIN CERTIFICATE-----
<your-certificate>
-----END CERTIFICATE-----
caCertificate: |
-----BEGIN CERTIFICATE-----
<your-ca-certificate>
-----END CERTIFICATE-----
wildcardPolicy: NoneOptional components
Contact your Account Executive or Customer Success Manager to confirm that your license includes an optional component before enabling it.
Command-over-HTTP
To enable Command-over-HTTP in the main chart:
commandOverHttp:
create: trueIf you use tunnel mode, also provide the tunnel secret:
commandOverHttp:
create: true
tunnelSecret: "<your-cohttp-secret>"For standalone Command-over-HTTP or Tines Tunnel installations, see Deploying optional components.
Custom banner
Display a custom banner in the Tines UI:
tinesApp:
optionalFeatureConfiguration:
TINES_BANNER_ENABLED: true
TINES_BANNER_COLOR: "#663399"
TINES_BANNER_TEXT: "Internal use only"Quote the hexadecimal color value in YAML.
Command runner connections
The chart enables sticky connections for the command runner with tinesApp.tinesCommandRunner.stickyConnections: true. Keep this enabled when using custom runtimes; disabling it breaks custom runtime support.
Next steps
With your values file prepared, follow Deploying Tines with Helm to install Tines.
To apply changes to an existing installation, follow Upgrading Tines with Helm.