Running CHT via docker compose behind reverse proxy

Is there some documentation I am missing for how to run the CHT (via docker compose) behind a reverse proxy (e.g. Traefik/Caddy)?

Essentially I am trying to follow these deployment instructions, but 443/80 on my host are already mapped to Traefik. So, I am trying to get Traefik to proxy everything to the nginx container. Everything seems to spin up okay and my Traefik dashboard shows the router being configured as expected, but I just get Gateway Timeouts when trying to curl my cht URL.

I am thinking that something in the nginx config is fighting with me. For example, I guess my CERTIFICATE_MODE is still set to the default SELF_SIGNED, but really I don’t want certs at all (since Traefik will handle that). However, there does not seem to be an option for no SSL…

Hey @jkuester ! Thanks so much for posting this question. As more and more CHT Core instances are being cloud hosted (mainly in Kubernetes or EKS etc, but still), this is great to expose how the HTTP traffic is routed in our setup.

What you’re talking about doing is very similar to using Elastic Load Balancer (ELB) or Application Load Balancer (ALB) in AWS. As such, you have two main options:

  1. What is normally done for production instances is don’t run the nginx service at all and then expose the api port directly to the reverse proxy. On the docs page you cited, there’s a link to the CHT Core compose file, referencing this, you would delete the nginx service on line 79. Then back up on the api service, around line 50, you would add a port stanza to the api service:

       - "5988:${API_PORT:-5988}"

    Finally, have your reverse proxy point to port 5988 and away you go!

    The reaming two options are sub-optimal, only for development!! It’s a bit messy to have both a reverse proxy and CHT Core’s nginx as nginx is literally already acting as a load balancer.

  2. If you’re using Caddy, you can turn off TLS validation like this where is IP the docker host running the CHT and is the domain you have the DNS and cert for: {
      tls /etc/caddy/fullchain.pem /etc/caddy/privkey.pem
      reverse_proxy {
        transport http {
  3. Finally, for a slightly more invasive fix, you can turn off the redirect so traffic to the HTTP port on nginx stays there (instead of getting redirected to HTTPS port):

    • list the nginx containers: docker ps --filter "name=nginx" --format '{{ .Names }}'
    • get shell on the one that applies. in this case it’s 4_4_test_nginx_1 for me: docker exec -it 4_4_test_nginx_1 bash
    • once in the container, edit the config: vi /etc/nginx/nginx.conf
    • around line 30 find the 3 lines that have location / { and then return 301 https://$host$request_uri; and finally }. Replace all three of those lines with just one: include /etc/nginx/conf.d/server.conf;
    • exit the container and restart it: docker restart 4_4_test_nginx_1
    • finally, find the non-https port for you helper instance. Mine was called 4_4_test.env so I ran: grep HTTP_ 4_4_test.env to get NGINX_HTTP_PORT=10098

Sorry! The first version of this response had an error in it for how I declared the new ports: stanza. It has since been fixed above - but if you grabbed a copy before I made this comment, please update it!

1 Like