Configuration

The Things Enterprise Stack can be configured using command-line flags, environment variables, or configuration files. See the Configuration Reference for more information about the configuration options.

In this guide, we will configure The Things Enterprise Stack using a configuration file, with an example domain thethings.example.com and TLS certificates from Let’s Encrypt.

To configure The Things Enterprise Stack , we will use the configuration file ttn-lw-stack-docker.yml, which contains configuration specific to our The Things Enterprise Stack deployment. When The Things Enterprise Stack starts, it looks for ttn-lw-stack-docker.yml for a license key, hostname, and other configuration parameters.

Download the example ttn-lw-stack-docker.yml used in this guide here.

To configure Docker, we also need a docker-compose.yml, which defines the Docker services of The Things Enterprise Stack and its dependencies.

Download the example docker-compose.yml used in this guide here.

Create a new folder where your deployment files will be placed. This guide assumes the following directory hierarchy:

docker-compose.yml          # defines Docker services for running The Things Enterprise Stack

config/
└── stack/
    └── ttn-lw-stack-docker.yml    # configuration file for The Things Enterprise Stack

Configure Docker

Docker runs an instance of The Things Enterprise Stack , as well as an SQL database and a Redis database which The Things Enterprise Stack depend on to store data.

We will configure Docker to run three services:

  • The Things Enterprise Stack

  • An SQL database (CockroachDB and PostgreSQL are supported)

  • Redis

SQL Database

We need to configure an SQL database, so in this guide we’ll use a single instance of CockroachDB. Make sure to find a recent tag of the cockroachdb/cockroach image on Docker Hub and update it in the docker-compose.yml file. Make sure that the volumes are set up correctly so that the database is persisted on your server’s disk.

The simplest configuration for CockroachDB will look like this (remember to replace latest with a version tag in production):

 5
 6
 7
 8
 9
10
11
12
13
  cockroach:
    image: cockroachdb/cockroach:latest
    command: start --http-port 26256 --insecure
    restart: unless-stopped
    volumes:
      - ${DEV_DATA_DIR:-.env/data}/cockroach:/cockroach/cockroach-data
    ports:
      - "127.0.0.1:26257:26257" # Cockroach
      - "127.0.0.1:26256:26256" # WebUI

NOTE: It also possible (and even preferred) to use a managed SQL database. In this case, you will need to update the is.database-uri configuration option to point to the address of the managed database.

Redis

We also need to configure Redis. In this guide we’ll use a single instance of Redis. Just as with the SQL database, find a recent tag of the redis image on Docker Hub and update it in the docker-compose.yml file. Again, make sure that the volumes are set up correctly so that the datastore is persisted on your server’s disk. Note that The Things Enterprise Stack requires Redis version 5.0 or newer.

The simplest configuration for Redis will look like this (remember to replace latest with a version tag in production):

28
29
30
31
32
33
34
35
  redis:
    image: redis:latest
    command: redis-server --appendonly yes
    restart: unless-stopped
    volumes:
      - ${DEV_DATA_DIR:-.env/data}/redis:/data
    ports:
      - "127.0.0.1:6379:6379"

NOTE: It also possible (and even preferred) to use a managed Redis database. In this case, you will need to update the redis.address configuration option to point to the address of the managed database.

The Things Enterprise Stack

We need to configure Docker to pull and run The Things Enterprise Stack . Below you see part the configuration of the stack service in the docker-compose.yml file. As with the databases, you need to find a recent tag of the thethingsindustries/lorawan-stack image on Docker Hub and update the docker-compose.yml file with that.

Entrypoint and dependencies

We tell Docker Compose to use ttn-lw-stack -c /config/ttn-lw-stack-docker.yml, as the container entry point so that our configuration file ttn-lw-stack-docker.yml is always loaded (more on the config file below). The default command is start, which starts The Things Enterprise Stack .

With the depends_on field we tell Docker Compose that The Things Enterprise Stack depends on CockroachDB and Redis. With this, Docker Compose will wait for CockroachDB and Redis to come online before starting The Things Enterprise Stack .

NOTE: If using a managed SQL or Redis database, these can be removed from depends_on and the services do not need to be started in Docker.

Volumes

Under the volumes section, we define volumes for files that need to be persisted on disk. There are stored blob files (such as profile pictures) and certificate files retrieved with ACME (if required). We also mount the local ./config/stack/ directory on the container under /config, so that The Things Enterprise Stack can find our configuration file at /config/ttn-lw-stack-docker.yml.

NOTE: If your ttn-lw-stack-docker.yml is in a directory other than ./config/stack, you will need to change this volume accordingly.

Ports

The ports section exposes The Things Enterprise Stack ’s ports to the world. Port 80 and 443 are mapped to the internal HTTP and HTTPS ports. The other ports have a direct mapping. If you don’t need support for gateways and applications that don’t support TLS, you can remove ports starting with 188.

In the environment section, we configure the databases used by The Things Enterprise Stack . We will set these to the CockroachDB and Redis instances that are defined in the docker-compose.yml above.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  stack:
    image: thethingsindustries/lorawan-stack:latest
    entrypoint: tti-lw-stack -c /config/ttn-lw-stack-docker.yml
    command: start
    restart: unless-stopped
    depends_on:
      - redis
      # If using CockroachDB:
      - cockroach
      # If using PostgreSQL:
      # - postgres
    volumes:
      - ./blob:/srv/ttn-lorawan/public/blob
      - ./config/stack:/config:ro
      # If using Let's Encrypt:
      # - ./acme:/var/lib/acme
    environment:
      TTN_LW_BLOB_LOCAL_DIRECTORY: /srv/ttn-lorawan/public/blob
      TTN_LW_REDIS_ADDRESS: redis:6379
      # If using CockroachDB:
      TTN_LW_IS_DATABASE_URI: postgres://[email protected]:26257/ttn_lorawan?sslmode=disable
      # # If using PostgreSQL:
      # TTN_LW_IS_DATABASE_URI: postgres://root:[email protected]:5432/ttn_lorawan?sslmode=disable

    ports:
      # If deploying on a public server:
      - "80:1885"
      - "443:8885"
      - "1881:1881"
      - "8881:8881"
      - "1882:1882"
      - "8882:8882"
      - "1883:1883"
      - "8883:8883"
      - "1884:1884"
      - "8884:8884"
      - "1885:1885"
      - "8885:8885"
      - "1887:1887"
      - "8887:8887"
      - "1700:1700/udp"

    # If using custom certificates:
    # secrets:
    #   - ca.pem
    #   - cert.pem
    #   - key.pem

NOTE: If using managed databased, the environment ports need to be changed to the ports of the managed databases.

Configure The Things Enterprise Stack

Once Docker starts The Things Enterprise Stack , we need to specify configuration options for running The Things Enterprise Stack in the ttn-lw-stack-docker.yml file. Let’s have a look at the configuration options which are required.

License

First is a license file. The Things Enterprise Stack requires a license, which can be purchased at the products page. This is specified in the license field, and can be either a key string, or a filepath. See the License Configuration Reference for more information.

TLS

The Things Enterprise Stack supports TLS with Let’s Encrypt. Since we’re deploying The Things Enterprise Stack on thethings.example.com, we configure it to only request certificates for that host, and also to use it as the default host (see the tls configuration reference section).

NOTE: Make sure that you use the correct tls depending on whether you will be using Let’s Encrypt or your own certificate files.

HTTP

We also configure HTTP server keys for encrypting and verifying cookies, as well as passwords for endpoints that you may want to keep for internal use (see the http section).

Email

The Things Enterprise Stack sends emails to users, so we need to configure how these are sent. You can use Sendgrid or an SMTP server. If you skip setting up an email provider, The Things Enterprise Stack will print emails to the stack logs (see the email section).

Component URLs

Finally, we also need to configure the URLs for the Web UI and the secret used by the console client (see the console section). These tell The Things Enterprise Stack where all its components are accessible.

NOTE: Failure to correctly configure component URLs is a common problem that will prevent the stack from starting. Be sure to replace all instances of thethings.example.com with your domain name!

Below is an example ttn-lw-stack-docker.yml file:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# The Things Stack requires a license key
license:
  # License contents may be specified directly
  key: ''
  # Or stored in a file
  # file: ''

# Identity Server configuration
# Email configuration for "thethings.example.com"
is:
  email:
    sender-name: 'The Things Stack'
    sender-address: '[email protected]'
    network:
      name: 'The Things Stack'
      console-url: 'https://thethings.example.com/console'
      identity-server-url: 'https://thethings.example.com/oauth'

    # If sending email with Sendgrid
    # provider: sendgrid
    # sendgrid:
    #   api-key: '...'              # enter Sendgrid API key

    # If sending email with SMTP
    # provider: smtp
    # smtp:
    #   address:  '...'             # enter SMTP server address
    #   username: '...'             # enter SMTP server username
    #   password: '...'             # enter SMTP server password

  # Web UI configuration for "thethings.example.com":
  oauth:
    ui:
      canonical-url: 'https://thethings.example.com/oauth'
      is:
        base-url: 'https://thethings.example.com/api/v3'

# HTTP server configuration
http:
  cookie:
    block-key: ''                # generate 32 bytes (openssl rand -hex 32)
    hash-key: ''                 # generate 64 bytes (openssl rand -hex 64)
  metrics:
    password: 'metrics'               # choose a password
  pprof:
    password: 'pprof'                 # choose a password

# If using custom certificates:
#tls:
#  source: file
#  root-ca: /run/secrets/ca.pem
#  certificate: /run/secrets/cert.pem
#  key: /run/secrets/key.pem

# Let's encrypt for "thethings.example.com"
tls:
  source: 'acme'
  acme:
    dir: '/var/lib/acme'
    email: '[email protected]'
    hosts: ['thethings.example.com']
    default-host: 'thethings.example.com'

# If Gateway Server enabled, defaults for "thethings.example.com":
gs:
  mqtt:
    public-address: 'thethings.example.com:1882'
    public-tls-address: 'thethings.example.com:8882'
  mqtt-v2:
    public-address: 'thethings.example.com:1881'
    public-tls-address: 'thethings.example.com:8881'

# If Gateway Configuration Server enabled, defaults for "thethings.example.com":
gcs:
  basic-station:
    default:
      lns-uri: 'wss://thethings.example.com:8887'
  the-things-gateway:
    default:
      mqtt-server: 'mqtts://thethings.example.com:8881'

# Web UI configuration for "thethings.example.com":
console:
  ui:
    canonical-url: 'https://thethings.example.com/console'
    is:
      base-url: 'https://thethings.example.com/api/v3'
    gs:
      base-url: 'https://thethings.example.com/api/v3'
    ns:
      base-url: 'https://thethings.example.com/api/v3'
    as:
      base-url: 'https://thethings.example.com/api/v3'
    js:
      base-url: 'https://thethings.example.com/api/v3'
    qrg:
      base-url: 'https://thethings.example.com/api/v3'
    edtc:
      base-url: 'https://thethings.example.com/api/v3'

  oauth:
    authorize-url: 'https://thethings.example.com/oauth/authorize'
    token-url: 'https://thethings.example.com/oauth/token'
    logout-url: 'https://thethings.example.com/oauth/logout'
    client-id: 'console'
    client-secret: 'console'          # choose or generate a secret

# If Application Server enabled, defaults for "thethings.example.com":
as:
  mqtt:
    public-address: 'https://thethings.example.com:1883'
    public-tls-address: 'https://thethings.example.com:8883'
  webhooks:
    downlink:
      public-address: 'thethings.example.com:1885/api/v3'

# If Device Claiming Server enabled, defaults for "thethings.example.com":
dcs:
  oauth:
    authorize-url: 'https://thethings.example.com/oauth/authorize'
    token-url: 'https://thethings.example.com/oauth/token'
    logout-url: 'https://thethings.example.com/oauth/logout'
    client-id: 'device-claiming'
    client-secret: 'device-claiming'          # choose or generate a secret
  ui:
    canonical-url: 'https://thethings.example.com/claim'
    as:
      base-url: 'https://thethings.example.com/api/v3'
    dcs:
      base-url: 'https://thethings.example.com/api/v3'
    is:
      base-url: 'https://thethings.example.com/api/v3'
    ns:
      base-url: 'https://thethings.example.com/api/v3'

NOTE: Make note of the client secret, as it will be needed again when initializing The Things Enterprise Stack .