Avoid network_mode: host for Docker

I am running home assistant inside a docker container for some month. Lately I started isolating my various containers in order to only expose the necessary ports to the outside world.

My home assistant container still runs with the network_mode:host setting, since auto-discovery and bluetooth require the host networking system. Is there a way to avoid using the complete host networking stack and instead only expose or mount the necessary ports to the container?

Or does home assistant always require the host networking stack to work properly?

Currently I am using the following docker-compose file:

version: '3'
services:

  homeassistant:
    image: homeassistant/raspberrypi3-homeassistant:latest
    container_name: homeassistant
    restart: always
    network_mode: host
    volumes:
      - /opt/home_assistant/:/config
      - /etc/localtime:/etc/localtime:ro
      - /media/usbstick/container/ssl:/ssl
3 Likes

You’ve already figured out the limitations: if you’re not using discovery, etc, then you’re fine to just pass 8123 into the container.

3 Likes

Is there an easy way to find all components which rely on discovery? I assume for these components I would need to explicitly configure everything in the configuration.yml

I am also using bluetooth, so I would need a way to make bluetooth available in the container. I couldn`t find a way yet to use bluetooth inside a container without using the complete host networking stack.

Before we go too far down that path - why do you want to switch away from host networking? You say you don’t want to expose everything to the “outside world”, but of course since the HA container doesn’t have a service on anything but port 8123 you wouldn’t be exposing anything more than you would if you exposed that port. If you’re really paranoid, you could set up a firewall on the Docker host to prevent incoming access to ports other than 8123 and whatever else you want to specify. And finally, unless you are putting your HA machine in a DMZ then nothing is actually exposed to the “outside world” (truly, in the sense of being outside your network), unless you are using port forwarding on your router. So not to discourage you from hardening your install, but think about the reasons before making things more difficult for yourself.

Thats a good point. My motivation is to consolidate all my various services running on my server behind a reverse proxy (https://traefik.io). This requires each container to have a connection to the traefik docker network, which unfortunately does not work if a container is using the host networking stack.

Therefore, I was looking into how I could potentially avoid this setting also for home assistant. If its to difficult I might just leave the setup as it is of course.

I don’t use host networking and discovery works for me
I only expose 8123(ha-frontend) and 8124(emulated-hue)

On the other hand I can’t get UPNP to work for emulated hue but refuse to believe this requires host networking

I don’t use docker compose but think you do
ports:
- 8123:8123

Funny - I’ve found your thread on google trying the exact same thing - hass in docker with traefik.

Did you ever manage to get it to work?

I’ve tried bridged, and simply specifying the ports, however I always seem to get “Gateway Timeout” from traefik. Only thing I haven’t tried yet is to put hass in the same docker network as traefik to see if that’ll work…

can you share your docker/treafik config ?

Now using cloud for alexa and GA…no issues.
If you run multiple apps on same server, host can become issue if ports conflict I believe

As far as I am aware traefik does not work with a container which uses the host networking stack, since it needs to route the traffic via a dedicated docker network to and from a container.
So it will only work if you only expose port 8123. Since I am using the homekit component, I have to run the container on the host network.

But I use traefik for a lot of other containers for internal services, such as pihole. Works really well!

You can bridge a vlan/interface with a docker container so it looks like a container is a vm/server on the same network. I use that in my swarm to tie Alexa bridge and broadlink devices without using host network. I’ll post the solution here a bit later - not at my pc now…

So, I use this on a docker swarm, so your use case may vary but for a swarm it requires 2 networks:

  1. one intermediary network on each node that connects to the same vlan/interface
  2. one global swarm network

Step 1: Create the intermediary network on each node

Here the network is 192.168.0.X
We want to allow 30 hosts on this network so we use ip-range = 192.168.0.128/27 which gives us hosts from .129 to .158

Replace $INTERFACE with the interface name: eth0, en1s1, etc…
Replace $INTERMEDIARY with the name of the docker network: vlan_x_intermediary, interface_eth0_intermediary, etc - this should be THE SAME on ALL nodes

docker network create \
		--config-only \
		--subnet="192.168.0.0/16" \
		--ip-range="192.168.0.128/27" \
		-o parent="$INTERFACE" \
		$INTERMEDIARY

Step 2: Create the swarm global network
This uses the $INTERMEDIARY network on each host.
Replace $NETNAME with a network name you can use in service network list (like vlan_home_automation, vlan_12, interface_0 etc)

docker network create \
            -d macvlan \
            --scope swarm \
            --config-from $INTERMEDIARY \
            $NETNAME

Now if you want to run a service that requires broadcast / etc (for example https://github.com/bwssytems/ha-bridge ) you can just add $NETNAME in the network list.

Hope it helps.

Hiya,

I’ve just set up traefik to use host networking, it seems to work OK.

Here’s my docker.compose for the service:

version: '3'

services:
  traefik:
    image: traefik:1.6.5-alpine
    labels:
      - traefik.frontend.rule=Host:traefik.mydomain.com
      - traefik.port=8081
      - traefik.enable=true
    ports:
      - "80:80"
      - "443:443"
    network_mode: "host"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /share/docker-conf/traefik/traefik.toml:/traefik.toml
      - /share/docker-conf/traefik/acme.json:/acme.json

The compose for the home assistant container:

version: '3'

services:
  homeassistant:
    image: homeassistant/home-assistant:0.73.2
    volumes:
        - /share/docker-conf/homeassistant:/config
        - /etc/localtime:/etc/localtime:ro
    labels:
      - traefik.frontend.rule=Host:ha.mydomain.com
      - traefik.port=8123
      - traefik.enable=true
    restart: always
    network_mode: host
    devices:
      - "/dev/ttyACM0:/dev/ttyACM0"
2 Likes

Thanks for sharing! I assume you are not using homekit or other components which rely on auto-discovery?

I’m not using home kit, however the discovery module did pick up my google home device and a chromecast without issues so I expect using host mode would be the way to go for those.

You need to use network_mode: host to do this however otherwise it can’t get out to the LAN.

I put traefik in host mode too so that it could access other local servers that aren’t within the docker container. Potentially this would allow you to access other machines on the LAN, but I haven’t needed to do that. The only port I forward through from the firewall / modem is https / 443. As long as traefik is hardened to this, there’s no other issues for security. Of course that doesn’t mean that messages that get forwarded through can’t do stuff to HA or whatever, but there’s no way around that short of taking HA off the internet entirely.

Putting HA into an intermediary network just stops it from accessing your lan, so you do need to trust HA. It’s probably pretty safe however being open source.

If you wanted to use an intermediary network for accessing docker containers I guess you could sort that out too and put the proxy both on the LAN as well as the intermediary network, but that’s not something I need at this point.

1 Like

I do faced the same problem.
I have created a network and my docker compose spawns puts all my services under that network so traefik will expose it. Unfortunately I had to use traefik in host mode as homeassistant won’t work well without host mode.
Particularly my xiaomi sensor wouldn’t work…

I’ve deal this situation by manual creating toml file for traefik. I’ve defined backed with default gateway in my docker network.

@Lapatoc Can you share your toml config to do that?

[frontends]
  [frontends.homeassistant]
    backend="homeassistant"
    entryPoints = ["http", "https"]
    passHostHeader = true
    proirity = 20
    [frontends.homeassistant.routes.docker_host]
      rule="Host:hass.homelab.loc"
 [backends]
   [backends.homeassistant]
     [backends.homeassistant.servers.host]
       url = "http://172.17.0.1:8123"
       weight = 10

I have just been looking at this, I am using a slightly different approach:

  • I tired bridge mode using a docker-compose default network and the traefik_proxy network but ran into the usual problems with discovery

  • I am already using a macvlan network for certain hosts so decided to put hass docker onto the macvlan AND the traefik_proxy network and for good measure the default docker-compose network

  • Bizzarely this seems to work - I cannot use the macvlan to talk to containers bridged off the docker host - this is a macvlan restriction but I can use the default network to talk to these

  • I am using the traefik_proxy network to link everything that needs to be proxied

So far everything seems to be working well. I am still finding references in my configuration to the docker host but am replacing them with hosts on the default network to restore connectivity ie. node-red.dockerhost.com:1880 simply becomes node-red:1880 using the default docker-compose network.

its a little more complex than I would like, maybe I should move everything to macvlan??