13 August 2021 / Last updated: 13 Aug 2021

Run your private The Things Stack network server on a Raspberry Pi with balena

Execution time: 1hr - 2hrs
Difficulty: Medium
Cost: High
Use this guide to learn how to build a standalone LoRaWAN server solution that runs on a Raspberry Pi and balena.
This solution uses The Things Stack LoRaWAN Network Server Open Source Edition and you can run it with one click. Running it using containers on balena means that it can run alongside with other services such as the balena LoRaWAN BasicsTM Station gateway. As a result, you can have all the LoRaWAN stack (gateway + network server) running together on a single Raspberry Pi.

Before you start


I think that Low-Power Wide Area Networks (LPWAN) are amazing. LoRaWAN (LoRa Wide Area Network) is an example of LPWAN. Using LoRa (Long Range) radio-frequencies, you can send tiny packages of data over long distances (even miles away depending on the topology) with simple battery-powered devices. The radio packets are captured by gateways which relay over the Internet the LoRa packages to network servers.
The Things Stack is an example of a LoRaWAN network server. This runs on the The Things Industries clusters that are distributed worldwide. However, if you want to manage your own data without sharing it with any cloud provider, the data collected can’t leave your country, or other similar requirements, then the solution is to deploy The Things Stack LoRaWAN Network Server using balena on a Raspberry Pi.

About TTS and recent changes

The Things Stack (TTS) is an open source LoRaWAN network server, built by The Things Industries. After the successful The Things Network (TTN) LoRaWAN network server, followed by thousands of developers all around the world, The Things Industries decided to migrate to a new open source network server. At the end of 2021 TTN (v2) is moving to the newest The Things Stack (TTS) (v3).
NOTE: TTN clusters will shut down in December 2021 and all the traffic from LoRa nodes need to be redirected to TTS v3.

TTS and the balena community

In the past, at balena we have helped developers from the TTN community to deploy their LoRaWAN gateways using balenaCloud and manage the fleet. The latest version of the LoRaWAN gateway balena introduced is the BasicsTM Station, and how to migrate the gateway from TTN V2 to TTS V3. You can use Deploy with balena by clicking the button Fork a fleet if you want to run your own TTS Basics Station gateway from balenaHub.
TTS allows you to build and manage LoRaWAN networks on your own hardware or in the cloud. In this case, you can run the complete stack on a Raspberry Pi 3 or 4. Manually installing the stack on a Pi can be challenging, but balena provides built-in capabilities to provision, deploy, and manage everything in one device. You can also easily scale the number of devices using the platform as well.
The project is open to more contributors who would like to introduce new services such as the Dashboard block, WiFi connect, NodeRed and more.

Hardware required

To build this project, you'll need the following:
  • Raspberry Pi 3 / 4 or balenaFin
  • An SD card if you’re using a Raspberry Pi
  • Power supply and (optionally) Ethernet cable
In case you want to add a LoRaWAN gateway service on the device you will need:

Software setup

For the software, you'll need:

Network setup (optional)

This is optional as the device runs automatically with its local IP. However you may want to have this in case you want to use it not for testing purposes or you would like to access it remotely:
  • A static IP for the device (either in the device or using a DHCP on your router)
  • A domain or subdomain pointing to the device IP.


Create the The Things Stack network server

To create the The Things Stack local network server on your Raspberry Pi click the Deploy with balena button below to automatically deploy the application on balenaCloud.
Clicking the deploy button will create an application with all the necessary code to deploy your The Things Stack.
Once all the services have been deployed on your device, copy your local IP and introduce on your browser https://your-local-ip-address-here. Otherwise, you can use the Public Device URL.
To access The Things Stack, use admin as a User ID and changeme as a password.
Now you are ready to add a new Gateway or a LoRa application connected to your private The Things Stack network server.

Adding a gateway into the stack

To deploy the BasicsTM Station gateway service along TTS local network server on your Raspberry Pi, click the Deploy with balena button below to automatically deploy the application on balenaCloud.
Clicking the deploy button will create an application with all the necessary code to deploy your The Things Stack plus basicstation service.
It’s time to connect your LoRa concentrator compatible with your Raspberry Pi or balena Fin (SX1301, or SX1302 and SX1303 such as RAK2245 or RAK 2287), to run the LoRaWAN gateway running alongside with The Things Stack network server.

Deploy it from balena CLI

The previous application was running The Things Stack Open Source Edition network server. However if you would like to run a gateway and the network server alongside on the same device, this is possible.
You will need the git CLI and balena CLI installed on your computer.
First thing you need to do is to clone the the-things-stack-balena repository on your device and update the submodules.
cd ~/workspace
git clone https://github.com/xoseperez/the-things-stack-balena
cd the-things-stack-balena
git submodule update --init
Let’s add to the stack the LoRaWAN Basics Station gateway. To add the project to the balena application:
Make sure the submodule is checked out on your local repository. If not, run git submodule init.
Edit the docker-compose.yml and uncomment the basicstation service.
  # -----------------------------------------------------------------------------------------------
  # git submodule add https://github.com/mpous/basicstation
  # -----------------------------------------------------------------------------------------------
    build: ./basicstation
    restart: unless-stopped
    privileged: true
    network_mode: host
      io.balena.features.kernel-modules: '1'
      io.balena.features.firmware: '1'
      io.balena.features.dbus: '1'
      io.balena.features.supervisor-api: '1'
      io.balena.features.balena-api: '1'
Make sure you have the balena CLI installed on your computer.
Push the code with balena push <your-application-name>. It will take 3-5 minutes to build this on the balenaCloud builders.
See the magic happening, your device is getting updated 🌟Over-The-Air🌟!

Add BasicsTM Station LoRaWAN gateway protocol

The service basicstation will appear on the list of services.
NOTE: You’ll notice that the services will reboot a few times. This is intended behavior as things get set up.
Now go to the Device Variables list and:
Add or modify MODEL depending on the LoRa concentrator model you have (SX1301, SX1302 or SX1303).
As explained in the Basics Station tutorial on TTS v3, now it’s time to configure the gateway on The Things Stack local server.
Copy your local IP address and paste it into the browser with https. You will need to accept the self-signed certificate that the device has generated automatically for your local IP address. You also can use the public URL generated by balena at this point.
As done before Login using the credentials User ID admin and the password changeme. Feel free to change your Password after you log in.
Go to Gateways and click Add new Gateway. Copy the EUI that the basicstation service introduces as a TAG of the device on the balenaCloud dashboard and paste it as the EUI of the gateway that you are registering.
Introduce the other data required.
Once the gateway is created, remember to generate an API Key. Go to Add API Key, then select Link as a Gateway .... Copy the key.
Paste the key on the Environment Variables of the device on balenaCloud as TC_KEY. The device will restart all the services a couple of times as the self-signed certificates are going to be regenerated.
From that moment, the device will be online on the The Things Stack network server and able to receive data.
NOTE: If you don’t use advanced networking configuration with static IP addresses and others, the IP address assigned to your device may change.

Configuring advanced networking

The previous version is running on the local IP assigned to your device by your router. However, this local IP may change after a reboot or other. If you would like to have a more stable solution we strongly recommend using a static IP or a domain if you would like to reach your network server from outside your local network.

Configuring a static IP

To configure a static IP on your balena device you will need to configure the network profile of your connectivity. There are two options:
  • Configure a static IP on the Raspberry Pi following the Network Manager balenaOS tutorial to set the static IP. This can be done directly on your SD card before booting it on your device, or editing the file and restarting the NetworkManager of the device.
  • Configure a static lease on your router linking the MAC address of the Raspberry Pi with an IP address. Requesting the IP using DHCP the router will return always the same IP address.

Configuring domain or subdomain

Once your device is always accessible with the same IP address (via DHCP or static IP) you can define a domain name pointing to the IP address. To set up the domain or subdomain there are two possibilities:
  • Using a DNS in your LAN such as dnsmask or PiHole (which runs a DNS server). To use PiHole as a DNS server you will need to change the balenaOS by default DNS servers pointing to to the PiHole address. To do that, edit the file /mnt/boot/config.jsonand add the following line:
    "dnsServers”: “<local-ip-your-piHole>”
  • Using a 3rd party service, such as Cloudflare. If you manage your domain from there you can just add an A register for a subdomain pointing to your local static IP address.
After setting up the new domain or subdomain, wait for the domain name to propagate and it should work. Remember, the variable TTS_DOMAIN on balenaCloud Environment Variables will create all the redirections and generate the self-signed certificates to enable The Things Stack network server to run properly under the new domain name.


This project involves a lot of services running together. If there is any issue not reported here, feel free to report it at the balena forums.

What happens if “Token exchange refused”?

If you are having certificates problems after the log in on The Things Stack or “token rejected” messages, you should try to regenerate the credentials by changing any of the SUBJECT_* variables. Another alternative is to access the stack service terminal and delete /srv/data/certificates_signature file and restart the service.
If the token exchange is still refused, get into the balenaCloud Environment Variables and check the variable TTS_DOMAIN. If you are not using advanced networking as explained before, copy your local IP and paste it at the TTS_DOMAIN variable. Then wait until the device gets restarted and the new self-signed certificates get generated with the local IP as if it’s not being propagated automatically.

What happens if the database fails

If the database fails to initialize on the logs, the best way to force the start script to init again is to change any of the TTS_ADMIN_* variables or TTS_CONSOLE_SECRET. Another alternative is to access the stack service terminal and delete /srv/data/database_signature file and restart the service.

Until next time

We’d love to hear from you if you try this project and add more sensors. We’re always interested to see how the community puts these projects to work. Get in touch with us on our Forums, Twitter, and Instagram to show off your work or to ask questions. We’re more than happy to help.


This project is made possible by the awesome work of Xose Pérez from RAK.
by Marc PousDeveloper Advocate