Skip to main content
Skip table of contents

Tenant configuration

The thingsHub's tenants are managed and configured using the Kubernetes package manager helm. Helm charts are provided at http://helm.smartmakers.de/index.yaml and are documented below. Each tenant is managed with a separate release and therefore with a separate helm configuration.

Heads-up notice

The base configuration of a tenant, as initially created in Creating a Tenant, should only be changed with extra care after the initial creation of the tenant. In particular, this includes the tenant's name and domain, as well as the configuration options affecting where and how data is persisted.

Example configuration file

The following is an example of a minimal configuration of a thingsHub tenant. For this documentation, we only provide the options for thingshub mode. Everything about "trackinghub" would be documentation that we do not want to expose in the public documentation. Please consult with us for further details.

Example Configuration File

Please do not copy and paste this example as it can be never complete or full updated. Please use the latest file in thingsHub helm chart gallery

YML
global:
  domain: thingshub.iot.yourdomain.com
  name: example
  tenant_mode: thingshub
  
  whitelabeling:
    enabled: true
    ...
    
  log:
    level: debug
    
  metrics:
    enabled: true
    stackdriver_project_id: sample-metrics-project
    
  tracing:
    enabled: true
    sampler: probabilistic
    service_rate: 0.01
    api_rate: 0.01
    exporter: stackdriver
    
  stackdriver:
    project_id: sample-project
    google_application_credentials: |
      {
        "type": "service_account",
        ...
      }
    
  smtp:
    enabled: true
    address: smtp.example.com:1234
    user: notifications@example.com
    password: abcd1234
    host: smtp.example.com
    from: notifications@example.com

  image:
    enabled: true
    registry: eu.gcr.io
    repository: repo.example.com
    tag: develop
    credentials:
      username: john
      password: abcd1234

  security:
    service_key: <randomly-generated service key>
    admin_password: <randomly generated password>
	password_policy_regex: <user defined regular expression>
    password_help_text: <user defined help text to show on user form>

  sql:
    host: hostname.domain:port
    database: example
    user: example
    password: <the example role's passsword on the sql server>

  tls:
    enabled: true
    cert: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    key: |
      ----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
      
  backup:
    sql: enabled
    influx: enabled
    sftp:
      host: sftp.example.com
      port: 1234
      user: john
      password: abcd1234
      remote_dir: /incoming/private

  nats:
    nats_url: nats://nats.example.com:4222
    is_cluster_wide: true
    user: john
    password: abcd1234

registry:
  master:
    url: https://drivers.example.com
    api_key: abcd1234

iam:
  keys:
    map:
      key: <your map API key >
      id:  <your map ID >
  rules:
    permissions: |
      rules:
        - policy: privilege
          pattern: devices:create
        - policy: deny
          pattern: devices:update

visualizer:
  image_renderer:
    enabled: true

  smtp:
    enabled: true
    host: smtp.example.com:587
    user: notifications@example.com
    password: abcd1234
    skip_verify: true
    from:
      address: notifications@example.com
      name: thingsHub

nats:
  enabled: false

influxdb:
  enabled: true

trackinghub:
  enabled: true
  gmaps:
    enabled: true
    access_token: <your geocoding API key >
    
postgresql:
  enabled: true
  fullnameOverride: postgresql
  postgresqlUsername: jane
  postgresqlPassword: abcd1234
  postgresqlDatabase: thingshub
  persistence:
    enabled: true

backup-cron:
  enabled: true

Updating a tenant’s configuration

The thingsHub helm chart repository is added with the following command:

CODE
$ helm repo add thingshub http://helm.smartmakers.de
...
$ helm repo update
...

To list all available helm charts in thingshub´s chart gallery use

CODE
$ helm search repo thingshub

The helm repo update command needs to be repeated before every upgrade to a newer version. To update a tenant configuration, first modify the config file as required, then run the helm tool with the following options:

CODE
$ helm upgrade --namespace <tenant> -f <tenant>.yaml <tenant> th-tenant
...
$

Helm chart configuration options

The thingsHub’s tenant chart is an umbrella chart which ties together multiple charts for the different services. Options which affect multiple sub-charts are put in the global section. Some of these options (wherever it makes sense) can be overridden for the sub-chart. These options are marked with an asterisk (*) at the end.

Name

Type

Description

global.domain

string

The base domain name, e.g. thingshub.smartmakers.de.

global.name

string

The name of the tenant, e.g. demo.

This must be alphanumeric, lowercase, and should be kept short but never longer than 63 characters. Dashes are allowed, neither in the beginning nor at the end and also never two consecutive ones.

This is concatenated with the value of global.domain to create the full domain name of the tenant, e.g. demo.thingshub.smartmakers.de.

global.tenant_mode

string

Defines the tenant mode of the thingshub system. For example, thingshub and trackinghub. For this documentation, we only provide the options for thingshub mode. Everything about "trackinghub" would be a documentation that we do not want to expose in the public documentation. Please consult with us for further details.

global.logos.light_name

string

The file name of the logo file. The filename suffix is used to identify the file type, e.g. svg or png.

global.logos.light_content

base64

The contents of the logo file encoded in base64. On Linux, the command cat <file> | base64 can be used to conveniently encode the file.

Keep this small and prefer a scalable format (i.e. svg) over a raster image format (e.g. png or jpg).

Container Images

global.image.registry *

string

The name of the registry from which to pull the container images. By default, this is docker-registry.smartmakers.de.

global.image.repository *

string

This is the path to the repository with the repository naming being the concatenation of the repository option and the name below. By default, this is things-hub.

global.image.name *

string

The name of the container image to pull. This is only meant to be overridden by each subchart.

global.image.tag *

string

The name of the tag to select for the images. The default tag is the version of the chart itself, i.e. docker image versions are tied to helm chart versions.

global.image.credentials.username *

string

The name used for pulling the container images

global.image.credentials.password *

string

The password used for pulling the container images

global.image.pullPolicy *

string

A policy, deciding when images should be pulled. Can be Always (for debugging), Never (for local debugging or in air-gapped networks), IfNotPresent (default).

Security (Authentication & Transport Layer Security)

global.security.service_key

string

A service key, shared by the services for mutual authentication.

global.security.admin_password

string

The password of the admin user.

global.security.password_policy_regex

string

Contains a regular expression as a value and basically reflects the desired  complexity/security of the user's passwords. In other words, when a new user is created or an existing user is updated via the REST API, the given password is checked against the defined regular expression. If such a check fails,  "HTTP 400 Bad Request" error and a message "user's password doesn't match security policy" is returned by the service. The default security policy ensures that any newly created password would match a string of any symbols with length no less than 10.

global.security.password_help_text

string

Contains the string to display on the user creation form to help users understand what the requirement for the password policy is.

global.security.system_user_ip_whitelist

string

The IP subnets from which admin login to the thingsHub is allowed. This is a comma-separated list of CIDR address ranges, e.g. 1.2.3.4/24, to allow any host in the subnet 1.2.3.x admin access to the thingsHub. Note that a personalized user with role TenantOwner can still access the system from other IP addresses. This only affects the built-in admin user.

global.tls.enabled

boolean

Enabled Transport Layer Security. This requires global.tls.cert and global.tls.key to be set.

global.tls.cert

string

The PEM-encoded TLS certificate for the domain name in <global.name>.<global.domain>. It is strongly recommended that this option is set to contain the entire certificate chain (excluding the root CA certificate) with the domain's own certificate first.

global.tls.key

string

The matching key for the certficate in global.tls.cert.

global.tls.issuer

string

The name of the TLS certificate issuer when using CertManager.

global.tls.kind

string

The kind of TLS certificate issuer, either Issuer or ClusterIssuer.

NATS (Additional Information: Configuring NATS for Individual Tenant)

global.nats.nats_url

string

The URL of the NATS that the tenant will connect to. It can be in-tenant deployed NATS, or a custom deployed NATS.

global.nats.is_cluster_wide

boolean

If the provided NATS is in-tenant deployed NATS or a cluster wide central NATS

global.nats.user

string

Username for the NATS account

global.nats.password

string

Password for the NATS account

PostgreSQL

global.sql.secret_ref.name

string

The name of the Kubernetes secret which contains the PosrtgreSQL database’s credentials.

global.sql.host

string

Hostname of the PostgreSQL server which hosts the tenants database. The default is postgresql.

global.sql.port

string

Port of the PostgreSQL server. The default is 5432.

global.sql.database

string

The database which stores the data of the different tenant’s services. The default is thingshub.

global.sql.user

string

The role with which the services shall access the PostgreSQL database. The default is thingshub.

global.sql.password

string

The password for the role with which the services shall access the PostgreSQL database.

global.sql.operator.enabled

string

Use the PostgreSQL operator to create the database secret.

global.sql.operator.server_ref

string

The database server on which the PostgreSQL operator shall create the database.

InfluxDB

global.influxdb.address

string

The hostname (with schema and port) of the InfluxDB server.

global.influxdb.user

string

The user with which to login to the InfluxDB server.

global.influxdb.password

string

The password for the above user.

global.influxdb.database

string

The database in which thingsHub shall store its data.

global.visualizer.auth.enabled

boolean

Set this to true to manage the Visualizer users with the thingsHub (recommended).

In Tenant Deployments

postresql.enabled

boolean

Deploy in-tenant postgresql instance

postresql.postgresqlUsername

string

Set the username for the instance

postresql.postgresqlPassword

string

Set the password for the instance

postresql.postgresqlDatabase

string

Set the database for the instance

postresql.persistence.enabled

boolean

Set if the instance will store the data in Kubernetes Persistence Volume Claim (PVC)

influxdb.enabled

boolean

Deploy in-tenant influx instance

nats.enabled

boolean

Deploy in-tenant nats instance

Email Notifications & SMTP

global.smtp.enabled

boolean

Enable SMTP notifications

global.smtp.insecure

boolean

Enable insecure mode for SMTP to connect to a SMTP server without any TLS check

global.smtp.ca_cert

string

Base64 encoded CA Certificate for the SMTP server. If provided, thingsHub will try to connecto to the SMTP server with self-signed CA certificate

global.smtp.address

string

The SMTP server’s address (e.g. smtp.gmail.com:587)

global.smtp.user

string

The username for logging into the SMTP server

global.smtp.password

string

The password for authentication at the SMTP server

global.smtp.host

string

The SMTP host name (this is usually identical to the address, except that this doesn’t contain the port, while the address usually does)

global.smtp.form

string

The “From” line of the email

Backup on SFTP

global.backup.sql

string

Backup the SQL database, for example enabled

global.backup.influx

string

Backup the Influx database, for example enabled

global.backup.sftp.host

string

Host of the SFTP server

global.backup.sftp.port

string

Port of the SFTP server

global.backup.sftp.user

string

User of the SFTP server

global.backup.sftp.password

string

Password of the SFTP server

global.backup.sftp.remote_dir

string

Directory on the SFTP server where the backup will be saved

backup-cron.enabled

boolean

Enable cron job for the backup

Miscellaneous

global.node.selector *

string

The node selector to force deployment of the tenant’s pods on specific nodes.

When overriding this option, the two maps for the base and overridden selectors will be merged.

global.log.level *

string

The lowest level of logs which shall be generated. One of debug, info, warning, error, fatal. By default, this is warning.

global.mqtt.qos *

string

The quality of service with which data shall be sent to the built-in MQTT broker.

grafana.plugins.hostPath

string

Set this to a path on the Kubernetes host machine in which Grafana plugins are stored. Make sure that the contents of this path are identical on all nodes of the cluster, so that grafana behaves consistently.

For each version of grafana in use, introduce a separate subpath with the version number, e.g. if the path is /mnt/plugins and some tenants are running version 5.0.4, the plugins for this tenant should be in the path /mnt/plugins/5.0.4.

registry.master.url

string

Driver registry master URL, from where to pull the drivers

registry.master.api_key

string

Driver registry API Key

iam.keys.map

object

API Key and ID of the Map for your user to be used in the UI.

trackinghub.gmaps.access_token

string

API Key for the google reverse geo-coding service.

iam.rules.permissions

multi-line scalar value

Mark some IAM permissions to be only available for priviledged user (for example, admin of the tenant)

White Labelling

color.headlinesPrimaryTextColor

string

Primary color of headlines like table headings, page name, e.g. “#595B5C"

color.buttonsPrimaryBackgroundColor

string

Primary background color of buttons like save buttons & create buttons.

e.g. “#007083"

color.buttonsPrimaryTextColor

string

Primary text color of buttons like save buttons & create buttons.

e.g. “#FFFFFF"

color.buttonsSecondaryBackgroundColor

string

Secondary background color of buttons like save buttons & create buttons.

e.g. “#FFFFFF"

color.buttonsSecondaryTextColor

string

Secondary text color of buttons like save buttons & create buttons.

e.g. “#192E35"

color.mainNavigationTenantNameBackgroundColor

string

Main navigation alias name and user name Avatar background color.
e.g. “#00BAD4"

color.mainNavigationIconsColor

string

Color of the main navation icons like setting and help. e.g. “#c2c2c2"

color.mainNavigationBackgroundColor

string

The background color of main navigation. e.g. “#007083"

color.mainNavigationMenuItemsTextColor

string

color of main navigation menu items like Tracking, Dashboard, Devices.
e.g. "#DC052D"

color.mainNavigationMenuItemsTextColorHover

string

Color of the main navigation menu items for mouse hover. e.g. "#DC052D"

color.mainNavigationMenuSubitemsTextColor

string

Text Color of main navigation items sub menu like sub menu of data is [Data Tables, Data Exchange, Integrations] e.g. "#0066B2"

color.mainNavigationMenuSubitemsTextColorHover

string

Text Color of mouse hover for main navigation items sub menu like sub menu of data is [Data Tables, Data Exchange, Integrations] e.g. "#DC052D"

logoLightBase64Content

base64 string

Logo image for our tenant that will appears on main navigation bar, login and logout page. e.g. "data:image/svg+xml;base64,P........... 0=

tenantAlias

string

Alias name for the tenant that will display on the main navigation. e.g. "Things Hub"

externalLinks.loginPage.link1
externalLinks.loginPage.link2
externalLinks.loginPage.link3

JS
textDe: string
urlDe: string
textEn: string
urlEn: string

External link for the user’s site will display on the login page right after the version number we can add up to three links.
both text and URL is required to display link on page if one of them is missing link will not display.
textDe, urlDe for german, and textEn, urlEn is for the English translation
e.g.

CODE
externalLinks:{ 
loginPage: {
        link1: {
          textDe: "Arsenal-Fußballverein",
          urlDe: "https://www.arsenalfc.de/",
          textEn: "Arsenal Football club",
          urlEn: "https://www.arsenal.com/"
        },
        link2: {
          textDe: "Mercedes-Benz Personenwagen",
          urlDe: "https://www.mercedes-benz.de/?group=all&subgroup=see-all&view=BODYTYPE",
          textEn: "Mercedes Benz passenger car",
          urlEn: "https://www.mercedes-benz.com/en/"
        },
        link3: {
          textDe: "Deutschland visum einwanderung",
          urlDe: "https://www.germany-visa.org/de/",
          textEn: "Germany visa immigration",
          urlEn: "https://www.germany-visa.org/"
        }
      }
}

externalLinks.helpMenu.openSupportTicketLink

JS
textDe: string
urlDe: string
textEn: string
urlEn: string

This will allow us to modify the open support ticket link in tenant help menu. Both text and URL is required to display link on page if one of them is missing will show the default link in menu.
textDe, urlDe for german, and textEn, urlEn is for the English translation

e.g.

CODE
externalLinks:{
helpMenu: {
openSupportTicketLink: {
          textDe: "Support Ticket bei Porsche öffnen",
          urlDe: "https://help.smartmakers.io/de/support/home",
          textEn: "Open Support Ticket",
          urlEn: "https://help.smartmakers.io/en/support/home"
        }
      }
}


externalLinks.helpMenu.link1
externalLinks.helpMenu.link2
externalLinks.helpMenu.link3

JS
textDe: string
urlDe: string
textEn: string
urlEn: string

External link for the user’s site will display uder the help menu we allow users to add up to three links.
both text and URL is required to display link on page if one of them is missing link will not display.
textDe, urlDe for german, and textEn, urlEn is for the English translation
e.g.

CODE
externalLinks:{ 
helpMenu: {
        link1: {
          textDe: "Arsenal-Fußballverein",
          urlDe: "https://www.arsenalfc.de/",
          textEn: "Arsenal Football club",
          urlEn: "https://www.arsenal.com/"
        },
        link2: {
          textDe: "Mercedes-Benz Personenwagen",
          urlDe: "https://www.mercedes-benz.de/?group=all&subgroup=see-all&view=BODYTYPE",
          textEn: "Mercedes Benz passenger car",
          urlEn: "https://www.mercedes-benz.com/en/"
        },
        link3: {
          textDe: "Deutschland visum einwanderung",
          urlDe: "https://www.germany-visa.org/de/",
          textEn: "Germany visa immigration",
          urlEn: "https://www.germany-visa.org/"
        }
      }
}

How to...

... set a logo for the index page

You require a logo in an image format supported by your browser. It is preferable to use a vector graphic (svg) over a raster image format. The logo must be supplied as a base64-encoded helm configuration option and suffix in the filename should match the real image type. Set the logo as in the example below:

YML
global:
  logos:
    light_name: company-logo.png
    light_content: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==

In order to convert the image to base64, you can use an online encoder such as: https://www.base64-image.de/ or search google for others. If you run a linux machine you can execute the following command

BASH
$ cat logo.png | base64 -w 0
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==
$

... generate a secure, random password on the command line

You can generate a secure, random password from the command line using the command line tool openssl:

BASH
$ openssl rand -base64 30
pNABkkecqQTdTrck9IzhrPgulvNY4qELUgaC3JDA
$

…change data retention policies

Retention policies cannot be set in the helm configuration, but need to be set directly in InfluxDB. For this, log into the InfluxDB with an admin user and execute the following commands:

CODE
ALTER RETENTION POLICY receptions_retention_policy ON <tenant-influxdb-name> DURATION 744h REPLICATION 1;
ALTER RETENTION POLICY thub_device_data ON <tenant-influxdb-name> DURATION 744h REPLICATION 1;
ALTER RETENTION POLICY logs_rp ON <tenant-influxdb-name> DURATION 744h REPLICATION 1;
ALTER RETENTION POLICY things ON <tenant-influxdb-name> DURATION 744h REPLICATION 1;

… create the PostgreSQL database secret

There are three ways to create a secret for the PostgreSQL database access:

Use a pre-defined secret

This is the default behavior. You create a secret of type Opaque or kubernetes.io/basic-auth with the fields hostname, port, database, username, password. Next you set the helm configuration option global.sql.secret_ref.name to the name of that secret. Now install the helm chart and all services will pick up the secret and connect to the SQL database.
This can also be used in combination with a tool such as terraform to create the secret.

Create a secret with the helm chart itself

Set the configuration options global.sql.hostname, global.sql.port, global.sql.database, global.sql.username, and global.sql.password. The helm chart will generate a secret automatically if it detects that the password option is set. The secret will be placed at global.sql.secret_ref.name. Note that with this option the secret is in the values.yaml file. As this file is usually checked into a version control system, this approach is depreciated.

Create a secret using the PostgreSQL operator

Do not set the any of the options from the above approach. Instead set the option global.sql.operator.enabled to true and the option global.sql.operator.server_ref to the name of the PostgreSQL server resource on which the database shall be created. The operator will create the database on the PostgreSQL server and then create the secret at global.sql.secret_ref.name for the tenant to use.

Password policy regex examples

The following examples for regular password policy checking regular expression can be used as inspiration for defining your own regular expressions:

Regular expression

Description

^.{8,}$

A password with at least 8 characters.

^(?=.*[A-Z])[A-Za-z\d@$!%*?&]{8,}$

Minimum eight characters, at least one uppercase letter

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$

Minimum eight characters, at least one uppercase letter, one lowercase letter and one number

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.