This document is a guide for setting up The Things Network's routing services in a local or private environment. If you already have some knowledge about how the backend works and if you are comfortable with a command line, this is the perfect place to start.
NOTE: This guide applies to the previous version (v2) of our network stack. To get started with the current version of our network stack (v3), go to ttn.fyi/v3/getting-started.
In this guide we will get everything up and running on your local machine (on localhost
). We will rely on the community account server of The Things Network (account.thethingsnetwork.org
) so that you can use your TTN Account to manage devices in your local network. If you don't want your environment to use community accounts, you can implement your own account server that is compliant with the Account Server API Specification.
Preparation
- Install and start Redis.
- Install and start Mosquitto
- Create a working directory. In this document we will use
~/ttn
. All commands are executed from this directory. - Download
ttn
(master
branch) macOS, 64 bit Linux, 32 bit Linux or arm Linux. - Download
gateway-connector-bridge
(master
branch) for macOS, 64 bit Linux, 32 bit Linux or arm Linux. We did not test this guide on Windows, but that might work too :)
The Discovery Server
The configuration for the Discovery server will be stored in ~/ttn/discovery/ttn.yml
:
id: mynetwork-discovery
tls: true
key-dir: discovery/
auth-servers:
ttn-account-v2: "https://account.thethingsnetwork.org"
local: "file://discovery/server.pub"
discovery:
master-auth-servers:
- ttn-account-v2
- local
This configuration creates a discovery server called "mynetwork-discovery". The server will use TLS and get its keys from ./discovery
. It uses the public TTN account server and a local certificate for authentication, and both "account servers" are seen as "master servers".
With this configuration in place, we will generate the public/private keypair for the Discovery server:
$ ttn discovery gen-keypair --config ./discovery/ttn.yml
Since we use TLS, we need to create a certificate for localhost
:
$ ttn discovery gen-cert localhost --config ./discovery/ttn.yml
You can now start the discovery server:
$ ttn discovery --config ./discovery/ttn.yml
Keep the discovery server running while you set up the other components.
Access Tokens
Routers, Brokers and Handlers authenticate with the discovery server using "access tokens". In the public community network you could get those with the command ttnctl components token [router/broker/handler] [id]
, but as we're building a private network, we have to manually create these access tokens with the command ttn discovery authorize [router/broker/handler] [id]
. For the Router you would use the following command:
ttn discovery authorize router mynetwork-router --config ./discovery/ttn.yml
You can use the access token that is printed to your console in the router's configuration. Use the appropriate commands to do the same for the Broker and Handler.
The Router
The configuration for the Router will be stored in ~/ttn/router/ttn.yml
:
id: mynetwork-router
tls: true
key-dir: router/
auth-servers:
ttn-account-v2: "https://account.thethingsnetwork.org"
discovery-address: "localhost:1900"
auth-token: THE DISCOVERY ACCESS TOKEN THAT YOU GENERATED FOR THE **ROUTER**
router:
server-address-announce: localhost
skip-verify-gateway-token: true
This configuration creates a router called "mynetwork-router". The server will use TLS and get its keys from ./router
. It uses the public TTN account server for authentication. It connects to the discovery server on localhost
and uses the access token we just generated to authenticate with the discovery server. The Router announces itself as being on the localhost
address. Furthermore it skips verification of the gateway token, because we're in a private network. You can remove this line if you do want to verify gateway tokens.
Just like with the discovery server, we have to generate a public/private keypair and a TLS certificate:
ttn router gen-keypair --config ./router/ttn.yml
ttn router gen-cert --config ./router/ttn.yml
In this case we don't have to specify that we're running on localhost
when generating the certificate. The command will just take that from the configuration file.
The TLS certificate we generated for the discovery server is not trusted by the operating system, so we have to manually trust it. To do so, we can append it to a ca.cert
file in the router
directory:
cat discovery/server.cert > router/ca.cert
You will have to do the same when you set up the Broker and Handler.
You can now test your configuration by starting the Router:
$ ttn router --config ./router/ttn.yml
The NetworkServer
The configuration for the NetworkServer will be stored in ~/ttn/networkserver/ttn.yml
:
id: mynetwork-networkserver
tls: true
key-dir: networkserver/
auth-servers:
ttn-account-v2: "https://account.thethingsnetwork.org"
Again we have to generate a public/private keypair and a TLS certificate:
ttn networkserver gen-keypair --config ./networkserver/ttn.yml
ttn networkserver gen-cert --config ./networkserver/ttn.yml
Access Token
Brokers authenticate with the NetworkServer using access tokens. You can create an access token with the following command:
ttn networkserver authorize mynetwork-broker --config ./networkserver/ttn.yml
The Broker
The configuration for the Broker will be stored in ~/ttn/broker/ttn.yml
:
id: mynetwork-broker
tls: true
key-dir: broker/
auth-servers:
ttn-account-v2: "https://account.thethingsnetwork.org"
discovery-address: "localhost:1900"
auth-token: THE DISCOVERY ACCESS TOKEN THAT YOU GENERATED FOR THE **BROKER**
broker:
server-address-announce: localhost
networkserver-cert: broker/networkserver.cert
networkserver-token: THE NETWORKSERVER ACCESS TOKEN THAT YOU GENERATED
The TLS certificate we generated for the discovery server and the NetworkServer are not trusted by the operating system, so we have to manually trust them. For the discovery server, we'll do the same as in the Router, for the NetworkServer, we can append the certificate to the ca.cert
file or we can copy the NetworkServer's certificate and set the networkserver-cert
in the configuration to broker/networkserver.cert
. We will do the latter.
cat discovery/server.cert > broker/ca.cert
cp networkserver/server.cert broker/networkserver.cert
Again we have to generate a public/private keypair and a TLS certificate:
ttn broker gen-keypair --config ./broker/ttn.yml
ttn broker gen-cert --config ./broker/ttn.yml
Now we will tell the discovery server which DevAddr
prefix we will handle with this Broker. In this case, we use a prefix that TTN reserved for private networks: 26000000/20
. This prefix allows you to issue 4096 distinct addresses to devices in your private network, which should be more than enough (remember that device addresses are not unique; you can easily give 100 devices the exact same address). If you need a larger address space, you should file a request with The Things Network Foundation. If you are setting up a large network, you might have to apply for your own NetID from the LoRa Alliance, which will give you your own prefix.
ttn broker register-prefix 26000000/20 --config ./broker/ttn.yml
The Handler
The configuration for the Handler will be stored in ~/ttn/handler/ttn.yml
:
id: mynetwork-handler
tls: true
key-dir: handler/
auth-servers:
ttn-account-v2: "https://account.thethingsnetwork.org"
discovery-address: "localhost:1900"
auth-token: THE DISCOVERY ACCESS TOKEN THAT YOU GENERATED FOR THE **HANDLER**
handler:
server-address-announce: localhost
broker-id: mynetwork-broker
mqtt-address: localhost:1883
Again we have to copy the discovery server certificate and generate a public/private keypair and a TLS certificate:
cat discovery/server.cert > handler/ca.cert
ttn handler gen-keypair --config ./handler/ttn.yml
ttn handler gen-cert --config ./handler/ttn.yml
The Bridge
TTN's backend components communicate using gRPC. Gateways, use different protocols, which are translated to gRPC with so-called bridges. The widely used packet_forwarder
protocol is handled by the gateway-connector-bridge
. If you followed this guide from the start, you should already have the correct version.
Unfortunately, this bridge does not support configuration files, so we will use CLI flags to configure it. We still need to have the discovery server certificate, so let's create an empty directory for the bridge and copy the discovery server certificate to the ca.cert
file:
cat discovery/server.cert > bridge/ca.cert
We will need the following command line arguments to connect the bridge to your private backend:
--ttn-discovery-server "localhost:1900"
--root-ca-file "bridge/ca.cert"
--ttn-router "mynetwork-router"
Starting Everything Together
Just run each of the following commands in separate tabs:
ttn discovery --config discovery/ttn.yml
ttn router --config router/ttn.yml
ttn networkserver --config networkserver/ttn.yml
ttn broker --config broker/ttn.yml
ttn handler --config handler/ttn.yml
gateway-connector-bridge --root-ca-file "bridge/ca.cert" --ttn-router "localhost:1900/mynetwork-router"
You can also use a Procfile
as shown below and use (for example) foreman
or forego
to start everything.
dsc: ttn discovery --config discovery/ttn.yml
rtr: ttn router --config router/ttn.yml
ns: ttn networkserver --config networkserver/ttn.yml
brk: ttn broker --config broker/ttn.yml
hdl: ttn handler --config handler/ttn.yml
br: gateway-connector-bridge --root-ca-file "bridge/ca.cert" --ttn-router "localhost:1900/mynetwork-router"
ttnctl
Configuration of ttnctl
is done by editing $XDG_CONFIG_HOME/config.yml
or ~/.ttnctl.yml
:
discovery-address: localhost:1900
mqtt-address: localhost:1883
router-id: mynetwork-router
handler-id: mynetwork-handler
ttnctl
also needs to have the discovery server certificate, for that we have to create a ca.cert
file in $XDG_DATA_HOME/ttnctl
, $XDG_CACHE_HOME/ttnctl
or ~/.ttnctl/
touch ~/.ttnctl/ca.cert
cat discovery/server.cert >> ~/.ttnctl/ca.cert
Now you can register your application to your private Handler:
ttnctl applications register
And manage your devices in the same way as you would do on the public community network.
Questions or Issues
If you have questions or remarks after following this guide, feel free use the forum or the #private-backend
channel on Slack. This is a community-supported guide, so please help each other out.
What's Next
You should now have a fully operational private backend. Now you should probably do some of the following:
- Read how to deploy the private backend using docker-compose
- Periodically update
ttn
to the latest version - Enable persistence in Redis
- Configure backups
- Secure your MQTT/AMQP broker with usernames and passwords
- Help with development of TTN's open source routing services