Setting up TTN stack V3 on DEBIAN

Trying to set up the latest version of the things stack V3 v3.2.4 on debian I´ve got stuck. I´m not asking for details here, more if someone can help me to help myself:

a) The stack is started calling docker-compose up. I suppose it is following docker-compose.yml, but I have no clue where to find more details about the setup. Maybe there is a good starting point on gitHub?

b) are there any logs that can tell us, why the setup fails? Can we somehow increase the verbosity?

c) Is there a more detailed description of the setup process?

Are you using the guides at ?

I followed the link on github:

You want to install The Things Stack ? Fantastic! Here’s the Getting Started guide.

→ For the latest Getting Started guide, visit

Anything wrong with this?

I posted my issues on #lorawan-stack@slack, but I have no clue how to look deeper into the details. Maybe it´s only a little typo…

found my issue: It sems, the stack needs ACME?!? See Slack for details

I used Certbot to create my certificates. Maybe need

For others running into issues it would help if you state both the issue and the solution here. Slack only keeps a (relatively) small amount of messages because we’re using the free version, this forum stores information much longer.

Do you mean it needs the acme folder in which you should store your certificates? The one mentioned on the “certificates” page? Or does it require more?

Did you put your own certificates in the local directory from which you ran docker-compose? If not the files (cert.pem and key.pem) could probably not be found by the process in the container.


Ok, so here is my issue: Following this example I tried in docker-compose.yml:

      # Let's Encrypt for "":
      # - TTN_LW_TLS_SOURCE=acme
      # - TTN_LW_TLS_ACME_DIR=/var/lib/acme
      # -
      # -
      # -

      # If using (self) signed certificates:
      - TTN_LW_TLS_SOURCE=file
      - TTN_LW_TLS_ROOT_CA=/etc/letsencrypt/live/
      - TTN_LW_TLS_CERTIFICATE=/etc/letsencrypt/live/
      - TTN_LW_TLS_KEY=/etc/letsencrypt/live/

that caused an error at docker-compose up:

stack_1      | error:cmd/internal/shared:initialize_gateway_server (could not initialize Gateway Server)
stack_1      | --- error:pkg/gatewayserver:listen_frontend (failed to start frontend listener `MQTT/tls` on address `:8882`)
stack_1      |     address=:8882
stack_1      |     protocol=MQTT/tls
stack_1      | --- open /etc/letsencrypt/live/ no such file or directory

Finally I tried

      # Let's Encrypt for "":
      - TTN_LW_TLS_SOURCE=acme
      - TTN_LW_TLS_ACME_DIR=/etc/letsencrypt/live/

      # If using (self) signed certificates:
      # - TTN_LW_TLS_SOURCE=file
      # - TTN_LW_TLS_ROOT_CA=/etc/letsencrypt/live/
      # - TTN_LW_TLS_CERTIFICATE=/etc/letsencrypt/live/
      # - TTN_LW_TLS_KEY=/etc/letsencrypt/live/

Nor the stack starts, but gives me an error on any https-call:

stack_1 | 2019/11/11 21:43:46 http: TLS handshake error from mkdir /etc/letsencrypt: permission denied

My files are in ~/TTN_V3/, so I tried ~/TTN_V3/acme for the pem-Files. Both acme-directory and pem-files are owned by docker user 886. This are the volumes settings:

      - ./blob:/home/pi/TTN_V3/blob
      # If using Let's Encrypt:
      - ./acme:/home/pi/acme

Currently there is no change, tried both versions with ./acme/ but results are similar:

1: — open ./acme/cert.pem: no such file or directory
2: no error, but page does not show up

I would change the docker-compose file back to the original paths for ‘own certs’ and put the cert and key in the same directory with the owner/permissions listed at the instructions. Then run docker-compose from that directory.

If this is the “Original”:

they use an absolute path:

If using (self) signed certificates:

  - TTN_LW_TLS_ROOT_CA=/run/secrets/cert.pem
  - TTN_LW_TLS_CERTIFICATE=/run/secrets/cert.pem
  - TTN_LW_TLS_KEY=/run/secrets/key.pem"

Did you mean I should start from there?!?

Yes, use that config and place the files in the same directory your docker-compose file is in. That path is within the container which has no relation to the host path.

Strange, seems to do the trick… This is my setting in docker-compose.yml.

      # If using (self) signed certificates:
      - TTN_LW_TLS_SOURCE=file
      - TTN_LW_TLS_ROOT_CA=/run/secrets/cert.pem
      - TTN_LW_TLS_CERTIFICATE=/run/secrets/cert.pem
      - TTN_LW_TLS_KEY=/run/secrets/key.pem

Does it mean, /run/secrets/ is not a path on my host machine, but in the docker container? It was really helpful to have some explanation in the comments…

Now, this is a step further (thanks for the support), I can see the login page, which comes with a valid certificate.

Just my login fails. On the console I see:

stack_1 | 2019/11/12 22:38:34 http: TLS handshake error from remote error: tls: bad certificate

TTN probably assumes people are familiar with the tools (docker-compose) they’re using? And may-be take a second time reading the instructions if things fail? I just read the pages you pointed to and found the answer I provided. However I do have the advantage of knowing docker (and compose) to some degree.
You could open an issue ticket suggesting the documentation is not clear…

I tried to follow the documentation as close as possible., but it´s true, I was not born on Thorwalds planet… On the other hand it´s easy to get confused with the way, docker fiddles around with Locations and permissions… AND you have to know, that docker-compose does not use any path other than the current and that a path in the setup is not a source but a target path.

That was the reason I asked for a good starting Point to look deeper into the setup process. Maybe there are some log files, that explain how things have been understood by docker-compose. Currently the packet is a black box. If things fail I have not more than what is printed out.

| |                                
| |__   ___   ___  _ __ __ _ _   _ 
| '_ \ / _ \ / _ \| '__/ _` | | | |
| | | | (_) | (_) | | | (_| | |_| |
|_| |_|\___/ \___/|_|  \__,_|\__, |
                              __/ |

Finally, with a little help from you all, I was able to get the stack up and running.

As a little writeup, there where two points I did not get from the documentation:

  1. There are some absolute path referenced in the docker-compose.yml. This are all target path for the containters that should not be changed. All sources need to be placed in the same folder as the docker-compose.yml like .\acme. During composition the files are moved by docker-compose to the referenced position.

  2. For Let’s Encrypt certificates, here is a short explanation from htdvisser:
    The Things Stack needs an acme directory where it can store the ACME account and certificate data. All you have to do is

    $ mkdir ./acme
    $ chown 886:886 ./acme

    In docker-compose.yml that ./acme folder on your host is mapped to /var/lib/acme in the container. And in the configuration of The Things Stack, you’ll tell it to use that /var/lib/acme folder. The first time you connect to The Things Stack using TLS (HTTPS), it will request certificates from Let’s Encrypt and store them in that folder

It was not clear to me how the ACME system works in the new stack. This is great! But if you use ACME, you must not include local certificates in your setup as i did. So, in this case you need to disable all settings with a comment: # If using (self) signed certificates in docker-compose.yml. As you can use your local Letsencrypt certificates in both ways, this was part of the confusion.

So thank everybody for your help!

1 Like

Could you help me to understand the issue of certificates, I don’t have much experience with Compose or Let’s Encrypt, I’m trying to install on an AWS instance, can you help me? Is a domain necessary?


I started with an IP only, but for Letsencrypt you need a domain. There are several options to get a cheap domain (e.g. If you have multiple IP´s running, you can use subdomains to link to them.

This topic was automatically closed after 30 days. New replies are no longer allowed.