Skip to content

Instantly share code, notes, and snippets.

@gaieges
Created March 8, 2020 16:14
Show Gist options
  • Save gaieges/936bdf91e01e4cc782eb047e5873089b to your computer and use it in GitHub Desktop.
Save gaieges/936bdf91e01e4cc782eb047e5873089b to your computer and use it in GitHub Desktop.
Homeassistant with traefik 2.2 for TLS in docker-compose in network_mode: host
version: '2.1'
services:
homeassistant:
restart: always
image: homeassistant/raspberrypi3-homeassistant
expose:
- 8123
ports:
- "8123:8123"
devices:
- /dev/ttyACM0
volumes:
- ./config:/config
network_mode: host
labels:
- "traefik.enable=true"
- "traefik.http.routers.hahttp.rule=Host(`MY_DOMAIN`)"
- "traefik.http.routers.ha.rule=Host(`MY_DOMAIN`)"
- "traefik.http.routers.ha.tls=true"
- "traefik.http.routers.ha.tls.certresolver=le"
- "traefik.http.routers.ha.tls.domains[0].main=MY_DOMAIN"
- "traefik.http.services.homeassistant.loadbalancer.server.port=8123"
traefik:
restart: always
image: traefik:v2.2
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--accesslog=true"
- "--providers.docker"
- "--providers.docker.exposedbydefault=false"
- "--entryPoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.tlschallenge=true"
- "--certificatesresolvers.le.acme.email=MY_EMAIL"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- 80:80
- 8080:8080
- 443:443
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
extra_hosts:
- host.docker.internal:172.17.0.1
@cstuder
Copy link

cstuder commented Apr 27, 2020

Typo in line 18.

Thank you, I don't fully understand how it works, but I made my installation work thanks to the extra_hosts field.

@gaieges
Copy link
Author

gaieges commented Apr 27, 2020

Great! hahttp is intentional, is that what you mean? It allows for a different router for https / http access

@cstuder
Copy link

cstuder commented Apr 27, 2020

Yes, I thought that was an accident. Guess I don't understand that line either. :-)

@gaieges
Copy link
Author

gaieges commented Apr 27, 2020

No worries! Looking through it again it looks like I removed some parts that contained local secrets and not that line which related to the local secrets

@m-fonseca
Copy link

Thank you, this was useful to me, both the load balancer line and extra host.

I'm not sure if

    expose:
      - 8123
    ports:
      - "8123:8123"

gives you anything because your in host mode though. I don't have it in mine and it works fine.

@cooperaj
Copy link

cooperaj commented Jun 5, 2020

Why this works I don't know. But it does!

Just adding the extra host line and things are routed correctly from a Traefik instance in a docker network to a homeassistant instance with 'network_mode: host'. Thanks!

@ajuch
Copy link

ajuch commented Sep 22, 2020

Works for me too. But I also don't understand what the extra_host does... Would be great if you could explain it!

@gaieges
Copy link
Author

gaieges commented Sep 22, 2020

The extra host stanza basically says if you need to talk to host.docker.internal, go to that specified IP instead. We're basically hardcoding the target for all of the requests going into traefik to go to the docker bridge IP

@HebelHuber
Copy link

HebelHuber commented Sep 23, 2020

Is the 172.17.0.1 ip universal or do I have to specify that elsewhere?

Edit: seems like it's the default for the IP address of the bridge interface (docker0 by default)

Found here
https://doc.traefik.io/traefik/providers/docker/#host-networking

@cooperaj
Copy link

It’ll be the IP of your default docker bridge network. Usually thats 172.17.0.1/24 but I’ve also seen 172.18.0.1/24. It’s possible to set the default range as a docker startup default but that depends on your platform.

@ajuch
Copy link

ajuch commented Sep 24, 2020

The extra host stanza basically says if you need to talk to host.docker.internal, go to that specified IP instead. We're basically hardcoding the target for all of the requests going into traefik to go to the docker bridge IP

Ah... traefik tries to resolve localhost with a DNS lookup to host.docker.internal. This is probably to support docker-for-windows, which uses this trick to reach the host. Now it makes sense, thanks!

@dorianim
Copy link

dorianim commented Feb 13, 2022

I had to add these to labels to avoid getting 400 bad request:

traefik.http.routers.ha.middlewares: haHeaders
traefik.http.middlewares.haHeaders.headers.customrequestheaders.Connection: Upgrade

@raccettura
Copy link

Thank you for this. I've spent a few hours before stumbling upon this little gem.

@othmanalikhan
Copy link

Thanks for this gist, helped me get my HA working.

@Weidav
Copy link

Weidav commented Aug 12, 2023

3 years later and "extra_hosts" still does the job, thank you!

@DSchougaard
Copy link

This took me hours to find - thanks for the help my man! :D

@matitalatina
Copy link

matitalatina commented Mar 30, 2024

If you want to avoid adding a "magic" IP address you can use

extra_hosts:
  - "host.docker.internal:host-gateway"

make sure you are using linux and docker >v20.10.

Source

If you receive "400 Bad Request" error, you need to whitelist the IP of the docker proxy in home assistant.

Check the Home Assistant logs. You should see something like:

2024-03-30 22:28:57.467 ERROR (MainThread) [homeassistant.components.http.forwarded] Received X-Forwarded-For header from an untrusted proxy XXX.XXX.XXX.XXX

Add the XXX.XXX.XXX.XXX IP in you home assistant configuration.yml file.

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - ::1
    - 127.0.0.1
    - XXX.XXX.XXX.XXX

This IP changes if you destroy your traefik container / network.
You can allow the CIDR 172.16.0.0/12 so it will be always allowed whatever IP it takes... But it's less secure of course.

@xZero707
Copy link

xZero707 commented Jun 20, 2024

@matitalatina That solved it for me. I was configuring Syncthing behind Traefik, while keeping it in host mode for broadcasting to work. Thank you.

@Yeastdonkey
Copy link

This IP changes if you destroy your traefik container / network. You can allow the CIDR 172.16.0.0/12 so it will be always allowed whatever IP it takes... But it's less secure of course.

I got around the insecurity by creating the traefik docker network such that it has an IP range for containers (10.0.0.0/22) that excludes the IP range I assigned traefik, but it is still within the same subnet (10.0.0.0/21):

Create docker network

docker network create \
  --driver=bridge \
  --gateway=10.0.0.1 \
  --subnet=10.0.0.0/21 \
  --ip-range=10.0.0.0/22 \
  traefik

Traefik compose.yaml

services:
  traefik:
    ...
    networks:
      traefik:
        ipv4_address: 10.0.4.2

@LukanRocks
Copy link

LukanRocks commented Jan 21, 2025

Hey folks

I'm also having issues.

I added:

extra_hosts:

  • "host.docker.internal:host-gateway"

To the traefik compose file to avoid magic ips even though it returns the 172.17.0.1

I have the:
expose:
- 8123
to HA compose file

Also have the trusted_proxies pointing to the subnet of my custom traefik proxy network

But I'm stuck on this page
Screenshot 2025-01-20 at 23 51 31

with a traefik log 504 Gateway Timeout error="dial tcp 172.17.0.1:8123: i/o timeout"

Any tips anyone?

everything is here: https://github.com/lukanvanderlinde/ubuntu-home-server

@xZero707
Copy link

Hey folks

I'm also having issues.

I added:

extra_hosts:

  • "host.docker.internal:host-gateway"

To the traefik compose file to avoid magic ips even though it returns the 172.17.0.1

I have the: expose: - 8123 to HA compose file

Also have the trusted_proxies pointing to the subnet of my custom traefik proxy network

But I'm stuck on this page Screenshot 2025-01-20 at 23 51 31

with a traefik log 504 Gateway Timeout error="dial tcp 172.17.0.1:8123: i/o timeout"

Any tips anyone?

everything is here: https://github.com/lukanvanderlinde/ubuntu-home-server

504 Gateway Time Out usually means that Traefik cannot reach the backend. Are you sure Traefik and HA are on the same network?

@LukanRocks
Copy link

Hey @xZero707 thanks for helping out. Nope, traefik is on it's own network

Traefik container file is using:
networks:
traefik-proxy:
name: traefik-proxy
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16

With the
extra_hosts:
- host.docker.internal:host-gateway

HA is network_mode: host

What I found weird is that traefik is recognizing the labels in HA, it's pointing to the right URL, it's displaying the HA can't connect but I receive different errors.

On the console log I get the one above (504 Gateway Timeout error="dial tcp 172.17.0.1:8123: i/o timeout"), on the browser I get:
Screenshot 2025-01-22 at 00 16 29

@Yeastdonkey
Copy link

HA is network_mode: host

What I found weird is that traefik is recognizing the labels in HA, it's pointing to the right URL, it's displaying the HA can't connect but I receive different errors.

I also ran into this issue when I set up HA, although I don't quite remember what I did to resolve it. What does your HA config look like? Here's mine:

configuration.yaml

# Loads default set of integrations. Do not remove.
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

homeassistant:
  external_url: "https://ha.domain.com"
  internal_url: "http://serverip:8123"

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 10.0.4.2

The important parts being external_url and internal_url as well as the http section. I think what I did to get it to work was hardcode the traefik container's IP under trusted_proxies. This was an issue, as described above, which I found a workaround for.

I also remember having an issue with getting traefik pointed to the right IP address using labels, but I think this was an unrelated issue, but I'll include below in case it's related:

For HA, which I have running in host mode, I have it configured via a config file, config.yaml, which is in the same directory as traefik.yaml. Note that you would need to include this file as a provider in your traefik.yaml. All of my other containers are configured via labels, and I remember this being significant at the time, but I don't remember if it was the fix to this specific issue or not. Here is how mine is configured:

traefik.yaml

providers:
  file:
    directory: /etc/traefik
    watch: true

config.yaml

http:
  routers:
    homeassistant:
      entryPoints:
        - web
        - websecure
      rule: "Host(`ha.domain.com`)"
      service: homeassistant
      tls: {}
  services:
    homeassistant:
      loadBalancer:
        servers:
          - url: "http://serverip:8123"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment