The Things Stack Helm chart is configured using yaml files. This guide assumes that these fields are saved in a <deployment>.values.yaml file and used for deployment/updates.
The following is a list of mandatory minimum fields. For a full list of possible values, check the values.yaml file at the root of the The Things Stack Helm chart. You can find it on artifacthub.io as well.
Warning:
Some values in this file are secrets. Make sure to check this file into a secure repository.Implications of choosing the domain and initial tenant
Note:
The global.domain, global.deployment.initialTenant.tenantID and global.tenancy.defaultID values determine how The Things Stack constructs its URLs and what your TLS certificates must cover.
Single-tenant deployments
For single-tenant deployments, set global.tenancy.defaultID to the tenant ID. This makes The Things Stack accessible directly at the configured domain without a tenant subdomain.
Example configuration:
global:
domain: thethings.example.com
deployment:
initialTenant:
tenantID: tti
adminUserID: admin-tti
adminPassword: ...
adminEmail: admin@example.com
tenancy:
defaultID: tti
With this configuration, The Things Stack is available at:
- Console:
https://thethings.example.com - API:
https://thethings.example.com/api/v3
The TLS certificate (referenced by global.ingress.tls.secretName) only needs to cover the base domain:
thethings.example.com
Multi-tenant deployments
Your license must support multi-tenancy to use this configuration. For multi-tenant deployments, set global.tenancy.defaultID to an empty string. Each tenant is then served on its own subdomain of the configured domain.
Example configuration:
global:
domain: thethings.example.com
deployment:
initialTenant:
tenantID: tti
adminUserID: admin-tti
adminPassword: ...
adminEmail: admin@example.com
tenancy:
defaultID: ""
With this configuration, the initial tenant is available at:
- Console:
https://tti.thethings.example.com - API:
https://tti.thethings.example.com/api/v3
When additional tenants are created, they are automatically served at https://<tenantID>.thethings.example.com. The TLS certificate must cover the base domain and a wildcard for tenant subdomains:
thethings.example.com*.thethings.example.com
The wildcard entry is required because each tenant is served on its own subdomain. Without it, browsers and API clients will reject the connection for any tenant-specific URL. No changes to the The Things Stack configuration or TLS certificates are needed when adding new tenants, as long as the wildcard certificate is in place.
license:
key: # License for The Things Stack
global:
domain: # Domain where The Things Stack deployment is exposed.
deployment:
initialTenant:
tenantID: # ID of the initial (first) tenant.
adminPassword: # Password for the Administrator of the tenant.
adminUserID: # User ID for the Administrator of the tenant. Do not use `admin`.
adminEmail: # Email of the Administrator of the tenant.
blob:
provider: # "aws", "azure", "gcp", "local" or empty string to disable blob usage.
aws: # Set only if provider is "aws".
region: # region
accessKeyID: # AWS access key ID
secretAccessKey: # AWS access key secret
azure: # Set only if provider is "azure".
accountName: # account name
clientID: # client ID
gcp: # Set only if provider is "gcp".
# Base64 encoded GCP credentials.json file.
# One option is to run `$ cat <credentials>.json | base64`.
credentials:
local: # Local Blob via a PV(C). The PVC must support the `ReadWriteMany` access mode.
pvc: # Name of the PVC.
cluster:
keys: # See preparation section.
http:
cookie:
blockKey: # See preparation section.
hashKey: # See preparation section.
metrics:
password: # See preparation section.
pprof:
password: # See preparation section.
redis:
address: # Address of the Redis Database end point.
password: # (Optional) Password to access Redis.
readOnly:
address: # (Optional) Address of the Redis Database read-only end point.
password: # (Optional) Password to access Redis.
console:
oauth:
clientSecret: # See preparation section.
ingress:
controller: # Ingress controller class name.
tls:
secretName: # Secret Name containing the TLS Certificates for the Domain.
tenancy:
adminKey: # See preparation section.
interop:
# Description: Interoperability configuration source.
# Expected value: "blob", "directory", "url" or empty string to disable blob usage
configSource: "blob"
blob:
# Description: Bucket for interoperability configuration.
# Expected value: string
bucket: ""
is:
# Postgres connection string
# Format : postgres://<username>:<password>@<host>:<port>/<database>?<options>
database:
uri:
profilePictures:
# Description: Bucket used for storing profile pictures
# Expected value: string
bucket: ""
endDevicePictures:
# Description: Bucket used for end device pictures
# Expected value: string
bucket: ""
dcs:
edcs:
blob:
bucket: # End Device Claiming Server bucket from "Section 4. Blob Storage"
The Things Indoor Gateway Pro configuration
The Helm chart does not support The Things Indoor Gateway Pro by default. To enable it in the Helm chart, The Things Gateway Controller must be enabled and the ingress controller of the Kubernetes cluster must have mTLS configured.
To set up the gateway controller, the following fields must be filled in values.yaml:
| Field name | Description |
|---|---|
global.ttgc.enabled |
The Things Gateway Controller enable flag. Set this to true. |
global.ttgc.domain |
Domain name of the cluster. Should be the same as global.domain. |
global.ttgc.tls.secretName |
Kubernetes Secret name containing the TLS. Should be the same as global.ingress.tls.secretName. |
global.ttgc.address |
(Optional) The URL of the gateway controller. It not specified, it defaults to gc.thethings.industries:443. |
Note:
In case you are using the cloud-managed The Things Gateway Controller (i.e.gc.thethings.industries:443), your network must be registered on The Things Gateway Controller, otherwise connections to the gateway controller will fail. Please contact The Things Industries support for registration.
The Things Stack verifies the identity of each connected TTIGPro gateway for security reasons, therefore mutual TLS is necessary to be configured in the ingress controller. mTLS configuration depends on the chosen ingress controller and is left to the operator of the Kubernetes cluster. The Things Stack recognizes the following client certificate header names:
X-Forwarded-Client-CertX-Forwarded-Tls-Client-Cert
As an example, the steps to configure Traefik to support mTLS are the following:
-
Create the Traefik middleware that passes the TLS client certificates in the request headers.
- Paste the k8s middleware manifest into a yaml file (make sure to set the correct namespace):
# traefik-passtlsclientcert.yaml apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: traefik-passtlsclientcert namespace: <traefik-namespace> spec: passTLSClientCert: pem: true- Apply the k8s manifest to the cluster:
kubectl apply -f traefik-passtlsclientcert.yaml
For more info check the Traefik docs on the PassTLSClientCert middleware.
-
Configure the default TLS options for Traefik.
- Paste the k8s middleware manifest into a yaml file (make sure to set the correct namespace):
# traefik-tlsoption.yaml apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default namespace: <traefik-namespace> spec: clientAuth: clientAuthType: RequestClientCert- Apply the k8s manifest to the cluster:
kubectl apply -f traefik-tlsoption.yaml
Note:
The Things Stack Helm chart uses wildcard domains in ingress routes. This is necessary for multi-tenant deployments as we don’t know the names of the tenants in advance. Traefik does not support TLS options for wildcard domains, because it maps the TLS options based solely on the host name (theHost part of the ingress rule) and it needs a concrete domain to match (check out more in the Traefik docs). To go around this limitation, a default TLS option can be used which is the fallback for any unmatched host.
For more info check the Traefik docs on TLS options.
- Set the protocol annotations for The Things Indoor Gateway Pro, middleware annotations and serviceAnnotations in
values.yaml(in addition to the existing annotations):
annotations:
ttigw:
traefik.ingress.kubernetes.io/router.entrypoints: ttigw,ttigwsecure
traefik.ingress.kubernetes.io/router.middlewares: traefik-passtlsclientcert@kubernetescrd
traefik.ingress.kubernetes.io/router.tls: "true"
serviceAnnotations:
traefik.ingress.kubernetes.io/service.serversscheme: h2c
- Install (or upgrade) the helm chart.