thethingsstack.io has moved to thethingsindustries.com/docs
Got it

v3.12

Getting Started Devices Gateways Integrations Reference
Get The Things Stack

Getting Started

    Overview
  • Quick Start
  • What Is The Things Stack?
  • Command-line Interface
  • Console
  • Installing The Things Stack
    • Configuration
    • Certificates
    • Running The Things Stack
    • Troubleshooting Installation
  • Migrating to The Things Stack
  • The Things Network
  • The Things Stack AWS Launcher
  • The Things Stack Cloud
  • Troubleshooting Getting Started
  • Upgrading The Things Stack
  • Users and Organizations
  • Using the API
  • Working with Events

Configuration

This guide shows an example of configuring The Things Stack using configuration files, with an example domain thethings.example.com and TLS certificates from Let’s Encrypt.

Note:
If configuring The Things Stack as localhost on a machine with no public IP or DNS address, see the localhost section.

Configuration Files

The Things Stack requires two configuration files when installing with Docker: docker-compose.yml and ttn-lw-stack-docker.yml.

Example files for Enterprise and Open source are provided below.

docker-compose.yml

docker-compose.yml defines the Docker services of The Things Stack and its dependencies, and is used to configure Docker.

ttn-lw-stack-docker.yml

ttn-lw-stack-docker.yml contains the configuration specific to The Things Stack deployment and is used to configure The Things Stack. When The Things Stack starts, it searches through ttn-lw-stack-docker.yml for component server addresses, a TLS certificate source, client authentication credentials, and other configuration parameters.

The configuration options in ttn-lw-stack-docker can also be specified using command-line flags or environment variables. All configuration options have a corresponding environment variable and command-line flag. See the Configuration Reference for more information about the configuration options.

This guide assumes the following directory hierarchy:

docker-compose.yml          # defines Docker services for running The Things Stack
config/
└── stack/
    └── ttn-lw-stack-docker.yml    # configuration file for The Things Stack

Example Configuration Files

  • Enterprise
  • Open Source

Download the example docker-compose.yml for The Things Stack Enterprise here.

Download the example ttn-lw-stack-docker.yml for The Things Stack Enterprise here.

Download the example docker-compose.yml for The Things Stack Open Source here.

Download the example ttn-lw-stack-docker.yml for The Things Stack Open Source here.

Note:

These example configuration files contain all of the configuration settings you need to run The Things Stack for development. Be sure to update ttn-lw-stack-docker.yml with your server address, generate keys in http.cookie and set console.oauth.client-secret.

For an extended explanation of the configuration settings, keep reading.

Settings in docker-compose.yml and ttn-lw-stack-docker.yml files are explained in detail in Docker Configuration and The Things Stack Configuration sections. Further, we provide tips for running The Things Stack in production.

Understanding Docker Configuration

In this section, configuring Docker is explained with an example docker-compose.yml file.

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

In docker-compose.yml file, Docker is configured to run three services:

  • An SQL database (CockroachDB and PostgreSQL are supported)
  • Redis
  • The Things Stack

SQL Database

To configure an SQL database, a single instance of CockroachDB is used in this guide. Note that the volumes need to be set up correctly so that the database is persisted on your server’s disk.

In production, replace the image with a working, stable tag from Docker Hub - CoackroachDB.

It is also possible (and even preferred) to use a managed SQL database. In this case, you will need to configure the managed database URI with the is.database-uri configuration option or TTN_LW_IS_DATABASE_URI environment variable.

The simplest configuration for CockroachDB looks like this (excerpted from the example docker-compose.yml):

 5
 6
 7
 8
 9
10
11
12
13
14
  cockroach:
    # In production, replace 'latest' with tag from https://hub.docker.com/r/cockroachdb/cockroach/tags
    image: cockroachdb/cockroach:latest
    command: start-single-node --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

Redis

The configuration in this guide uses a single instance of Redis. Again, note that the volumes need to be set up correctly so that the datastore is persisted on your server’s disk.

Note:
The Things Stack requires Redis version 5.0 or newer.

In production, replace the image with a working, stable tag from Docker Hub - Redis.

It is also possible (and even preferred) to use a managed Redis database. In this case, you will need to configure the managed database address with the redis-address configuration option or TTN_LW_REDIS_ADDRESS environment variable.

The simplest configuration for Redis looks like this (excerpted from the example docker-compose.yml):

28
29
30
31
32
33
34
35
36
  redis:
    # In production, replace 'latest' with tag from https://hub.docker.com/_/redis?tab=tags
    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"

The Things Stack

Entrypoint and dependencies

Docker Compose uses ttn-lw-stack -c /config/ttn-lw-stack-docker.yml as the container entry point, so that ttn-lw-stack-docker.yml configuration file is always loaded (more on the config file below).

In production, replace the image with a working, stable tag from Docker Hub - The Things Industries for Enterprise, or Docker Hub - The Things Network for Open Source.

The default command is start, which starts The Things Stack.

39
40
41
42
43
  stack:
    # In production, replace 'latest' with tag from https://hub.docker.com/r/thethingsindustries/lorawan-stack/tags
    image: thethingsindustries/lorawan-stack:latest
    entrypoint: tti-lw-stack -c /config/ttn-lw-stack-docker.yml
    command: start

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

45
46
47
48
49
50
    depends_on:
      - redis
      # If using CockroachDB:
      - cockroach
      # If using PostgreSQL:
      # - postgres
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, volumes for the files that need to be persisted on the disk are defined. There are stored blob files (such as profile pictures) and certificate files retrieved with ACME (if required). Also, local ./config/stack/ directory is mounted on the container under /config, so that The Things Stack can find the configuration file at /config/ttn-lw-stack-docker.yml.

51
52
53
54
55
    volumes:
      - ./blob:/srv/ttn-lorawan/public/blob
      - ./config/stack:/config:ro
      # If using Let's Encrypt:
      - ./acme:/var/lib/acme
Note:
If your ttn-lw-stack-docker.yml is in a directory other than ./config/stack, you will need to change this volume accordingly.

Environment and Ports

The databases used by The Things Stack are configured in the environment section. In this guide, these are set to the CockroachDB and Redis instances that are mentioned above.

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

The ports section exposes The Things Stack’s ports outside the Docker container. 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 use TLS, you can remove ports starting with 188:

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
    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://root@cockroach:26257/ttn_lorawan?sslmode=disable
      # # If using PostgreSQL:
      # TTN_LW_IS_DATABASE_URI: postgres://root:root@postgres: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"
      - "1888:1888"
      - "8888:8888"
      - "1700:1700/udp"

Understanding The Things Stack Configuration

Configuration options for running The Things Stack are specified in the ttn-lw-stack-docker.yml file. This section points out the required configuration options.

The example ttn-lw-stack-docker.yml file for The Things Stack Enterprise shown below contains details which help you follow this section.

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# 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: 'noreply@thethings.example.com'
    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'

  # If running a multi-tenant environment, configure tenant admin keys
  tenancy:
    admin-keys: ''                  # generate 32 bytes (openssl rand -hex 32)

# 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: 'you@thethings.example.com'
    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:
  # Configuration required for the Storage Integration
  packages:
    storage:
      provider: postgres
      bulk:
        enabled: true
      postgres:
        # if using CockroachDB
        database-uri: postgres://root@cockroach:26257/ttn_lorawan_dev?sslmode=disable
        # if using PostgreSQL or TimescaleDB
        # database-uri: postgres://root:root@postgres:5432/ttn_lorawan_dev?sslmode=disable
        insert-batch-size: 1024     # batch size for INSERT operations
        select-batch-size: 1024     # batch size for SELECT operations
  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'

# If running a multi-tenant environment, defaults for "thethings.example.com":
tenancy:
  base-domains: 'thethings.example.com'
  default-id: 'default'
Note:
The example ttn-lw-stack-docker.yml file is available for download in the Example Configuration Files section.

License

The Things Stack Enterprise 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

This example shows the configuration for using TLS with Let’s Encrypt. Since The Things Stack is being deployed on thethings.example.com in this guide, it is configured to only request certificates for that host, and also to use it as the default host.

If using Let’s Encrypt, certificates will automatically be requested the first time you access The Things Stack. You will notice that the page takes some time to load while certificates are obtained in the background.

See the TLS Options configuration reference for more information.

Note:
Make sure that you use the correct tls configuration depending on whether you are using Let’s Encrypt or your own certificate files.
Note:
If you are using your own certificate files, make sure to uncomment the lines that define source type, root-ca, certificate and key. The paths assigned to these do not need to be altered, because they point to the location of these files inside the Docker container, and not on your machine.

HTTP

In the http section, HTTP server keys for encrypting and verifying cookies are configured, as well as passwords for endpoints that you may want to keep for the internal use.

Email

The Things Stack sends emails to users, so the email section of the configuration defines how these are sent. You can use Sendgrid or an SMTP server. If you skip setting up an email provider, The Things Stack will print emails to the stack logs.

Component URLs

Finally, the console section configures the URLs for the Web UI and the secret used by the console client. These tell The Things Stack where all its components are accessible.

Note:
The client-secret will be needed later when authorizing the Console. Be sure to set and remember it!
Warning:
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!

Multi-tenancy

If running a multi-tenant environment, we need to configure the default tenant ID, and the base domain from which tenant IDs are inferred. See the tenancy configuration reference.

Running The Things Stack as localhost

Follow this section if you are configuring and running The Things Stack on a local machine with no public IP or DNS address.

localhost has a different meaning on your machine than inside the Docker container where The Things Stack runs, which can cause problems if you use localhost in your configuration.

localhost addresses on your machine will resolve to your machine, while localhost inside the Docker container will resolve inside the Docker container. In docker-compose.yml, we forward requests on ports 80 and 443 to ports 1885 and 8885 inside the container, so visiting localhost (which is really localhost:80) on your machine actually takes you to localhost:1885 within the container.

If you configure your is.oauth.ui.canonical-url as localhost, this causes Token Exchange Refused errors when you try to log in to The Things Stack Console, because an authorization request generated from within the container will not be redirected to port 1885 or 8885, where The Things Stack is listening.

Solution 1: Use the IP address of your computer on your local network

The best solution is to configure and use a static IP address for your machine on your local network so that redirects from your machine, from the Docker container, or from anywhere inside your local network, all resolve at the same place, on your machine.

Follow instructions here for configuring a static IP address on your computer. Use that IP address as your server address, i.e replace thethings.example.com with that IP address. You may also generate a self-signed certificate for that IP address by following instructions in the Certificates section.

Note:
ACME will not work on localhost, so you must either generate custom certificates for your IP address as shown in the Custom Certificate Authority instructions, or use http (unsecure) in your configuration.

This will still allow you to see The Things Stack Console by entering localhost or your local IP address in your browser. It will also allow you to connect to The Things Stack from any machine inside your local network.

You will also need to configure the CLI, to use the static IP of your machine as the address of The Things Stack.

Solution 2: Specify the internal ports that The Things Stack listens on in your configuration files

By default, The Things Stack listens on ports 1885 and 8885 inside Docker. To make localhost work both on your local machine and within the Docker container, append the port to localhost and make sure port forwarding is enabled in your docker-compose.yml for that port.

You must also remove ports 80 and 443 from your The Things Stack Docker configuration.

For example,

is:
  oauth:
    ui:
      canonical-url: 'https://thethings.example.com/oauth'
      is:
        base-url: 'https://thethings.example.com/api/v3'

becomes

is:
  oauth:
    ui:
      canonical-url: 'https://localhost:8885/oauth'
      is:
        base-url: 'https://localhost:8885/api/v3'

and in docker-compose.yml, add the following port forwarding configuration (if it does not already exist), while removing ports 80 and 443:

services:
  stack:
    ports:
      stack:
        - "1885:1885"
        - "8885:8885"
        # - "80:80" # Do not forward port 80
        # - "443:443" # Do not forward port 443

This will result in visits from both outside and inside the Docker container being received at the correct port by The Things Stack.

← Installing The Things Stack Certificates →

On this page

  • Configuration Files
  • Example Configuration Files
  • Understanding Docker Configuration
  • Understanding The Things Stack Configuration
  • Running The Things Stack as localhost

The Things Stack

Getting Started

Devices

Gateways

Integrations

Reference

Contributing

GitHub

Forum

About Us

The Things Network

The Things Industries

About this page

Last changed by Johan Stokking on 23 Mar 2021.
doc: Use backticks for localhost

Edit on Github