Skip to content
Home » Docker Compose Stack for Home Assistant with Grafana and InfluxDB

Docker Compose Stack for Home Assistant with Grafana and InfluxDB

  • by

Anebula is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Documentation on this from a Docker Compose angle is sparse, so I wanted to share my stack that I’ve had running reliably for over a year. I run it on a Proxmox Virtual Machine, but your setup could differ so just keep in mind that this stack can run on any VM or bare metal setup.

Why should I run Home Assistant on Docker instead of via HA OS?

I went back and forth here initially, first with Docker, then HA OS, and then back to Docker. I started with Docker because that’s my preferred method to run services on my servers, but early on I began to wonder if HA OS had features I was missing out on, so I made the jump to HA OS. Then with HA OS I started to run into issues with Zigbee/Z-Wave devices disconnecting and troubleshooting wasn’t as straightforward as it was with Docker, so I made the jump back. I learned that my Docker setup was more reliable and that I wasn’t missing out on any features. On top of that, I could utilize the Docker troubleshooting skills that I had acquired over the years.

The stack consists of 7 containers:

Home Assistant – [required] This is the foundation of the stack and serves Home Assistant itself.

Mosquitto – [required] This is used by Zigbee2MQTT as a pub/sub event bus for devices. Zigbee2MQTT broadcasts events onto Mosquitto and Home Assistant is subscribed to those events.

Node-Red – [optional] This is an advanced automation platform for more intricate logic. I don’t use this as much now since Home Assistant improved in this area, but it’s still useful for handling advanced automation.

Zigbee2MQTT – [required] This is the bridge between the Zigbee USB dongle and Mosquitto. Zigbee2mqtt doesn’t communicate directly with HA, but rather through Mosquitto.

Zwave-JS-UI – [required] This is the bridge between the Z-Wave USB dongle and Home Assistant. This does communicate directly with Home Assistant and does not use Mosquitto.

InfluxDB – [optional] This is for long-term data storage outside of Home Assistant. Home Assistant sends events directly to InfluxDB via its built-in integration support. As a data nerd, I needed more reporting capabilities than Home Assistance offered, so I opted for InfluxDB + Grafana since this is the recommended upgrade. However, Home Assistant will store its own history whether you use InfluxDB + Grafana or not, so know that Home Assistant doesn’t care if you enable this.

Grafana – [optional] This is the visualization layer on top of InfluxDB and gives far greater customization options.

docker-compose.yml
services:
  homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:stable
    environment:
      - TZ=America/Los_Angeles
    volumes:
      - home-assistant:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    # Try unprivileged:false first, I believe you only need to enable it if you have 
    # device pass-through issues for this container. In my case, I delegate device control 
    # to Zigbee2MQTT and Zwave-JS-UI, so homeassistant definitely did not need to be 
    # privileged. Furthermore,  Zigbee2MQTT and Zwave-js-ui containers also work fine 
    # without extra privilege. 
    privileged: false
    network_mode: host

  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    restart: unless-stopped
    ports:
      - "1883:1883"
    command: "mosquitto -c /mosquitto-no-auth.conf"
    volumes:
      - mosquitto:/mosquitto/data

  node-red:
    container_name: nodered
    image: nodered/node-red:latest
    restart: unless-stopped
    environment:
      - TZ=America/Los_Angeles
    ports:
      - "1880:1880"
    volumes:
      - nodered:/data

  zigbee2mqtt:
    container_name: zigbee2mqtt
    restart: unless-stopped
    image: koenkk/zigbee2mqtt
    volumes:
      - zigbee2mqtt:/app/data
      - /run/udev:/run/udev:ro
    ports:
      - "8080:8080"
    environment:
      - TZ=America/Los_Angeles
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB1

  zwave-js-ui:
    container_name: zwave-js-ui
    image: zwavejs/zwave-js-ui:latest
    restart: unless-stopped
    tty: true
    stop_signal: SIGINT
    environment:
      - SESSION_SECRET=ErJggHGhQW35jJ6g7H454447GWW
      - ZWAVEJS_EXTERNAL_CONFIG=/usr/src/app/store/.config-db
      # Uncomment if you want log times and dates to match your timezone instead of UTC
      # Available at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
      - TZ=America/Los_Angeles
    devices:
      # Do not use /dev/ttyUSBX serial devices, as those mappings can change over time.
      # Instead, use the /dev/serial/by-id/X serial device for your Z-Wave stick.
      - '/dev/serial/by-id/usb-Zooz_800_Z-Wave_Stick_533D054242-if00:/dev/zwave'
      # run this command: ls -l /dev/serial/by-id/*
    volumes:
      - zwavejsui:/usr/src/app/store
    ports:
      - "8091:8091" # port for web interface
      - "3000:3000" # port for Z-Wave JS websocket server


  influxdb:
    container_name: influxdb
    image: influxdb:2
    restart: unless-stopped
    volumes:
      - influxdb-data:/var/lib/influxdb2
      - influxdb-config:/etc/influxdb2
    environment:
      - name=value
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=homeassistant
      - DOCKER_INFLUXDB_INIT_PASSWORD=yr6w4X8tvSQnyW3F
      - DOCKER_INFLUXDB_INIT_ORG=homeassistant
      - DOCKER_INFLUXDB_INIT_BUCKET=homeassistant
    ports:
      - "8086:8086"


  grafana:
    container_name: grafana
    image: grafana/grafana:latest
    restart: unless-stopped
    volumes: 
      - grafana:/var/lib/grafana
    depends_on:
      - influxdb
    ports:
      - "3030:3000"

volumes:
  home-assistant:
  nodered:
  zigbee2mqtt:
  zwavejsui:
  mosquitto:
  influxdb-data:
  influxdb-config:
  grafana:

To put up your stack and view logs:

docker compose up -d && docker compose logs -f 

To manually update your stack – this will update all your images to the latest version available.

Bash
docker compose pull
docker compose up --force-recreate --build -d
docker image prune -f

Personally I update the stack automatically once a week via Watchtower, but keep in mind that this can cause issues if for example one container has breaking changes that aren’t handled automatically. I haven’t experienced any issues with automated updates, but I also have the peace of mind of using Proxmox restore in a pinch if I need to.

docker-compose.yml
services: 
  watchtower:     
    image: containrrr/watchtower
    container_name: watchtower 
    restart: unless-stopped
    environment: 
      WATCHTOWER_SCHEDULE: "0 0 4 * * 3" 
      TZ: America/Los_Angeles
      WATCHTOWER_CLEANUP: "true" 
      WATCHTOWER_DEBUG: "false"      
    volumes: 
      - /var/run/docker.sock:/var/run/docker.sock

# runs at 4am on Wednesdays

Proxmox VM

You’ll need to download the Debian ISO debian-12.7.0-amd64-netinst.iso or find a different version depending on your hardware here.

Base Operating SystemDebian 12 Bookworm
Memory6.00 GB
BIOSSeoBIOS
DisplayDefault
Machinei440fx
SCSI ControllerVirtIO SCSI single
Hard Diskdiscard=on,iothread=1,size=64G
Network DeviceVirtIO (paravirtualized)
USB DeviceSelect your Zwave USB
USB DeviceSelect your Zigbee USB

Additional Steps

  • Before putting up the stack, you must map your Z-Wave and Zigbee device locations to line 52 and line 69 of the Docker compose file. Look up the documentation for Zigbee2MQTT and Zwave-JS-UI to find these for your OS.
    • For Zigbee, I recommend the SONOFF Zigbee 3.0 USB Dongle. I’ve been running one for over 2 years without any issues.
    • For Z-Wave, I recommend the Zooz 800 Series ZST39 . I’ve been running the 800 series for a few months now and before that, I was using the older Zooz 700 series USB dongle for over a year without any problems.
    • For both dongles above and any Zigbee or Z-Wave dongle in general, it is always recommended to use a USB extension cable so that the dongles are separated from the server to minimize interference. I use these ITD ITANDA 10FT USB 3.0 Extension Cables, you’ll need two cables, one for each dongle.
  • When you put up the stack for the first time, you’ll need to go through the Home Assistant, Zigbee2Mqtt, Zwave-JS-UI, Nodered, InfluxDB, and Grafana configuration so that they all talk to each other. I would go in this order:
    • Set up Home Assistant (http://serverip:8123) and add the MQTT integration (Settings > Devices and Services > Add Integration > MQTT. Broker: localhost and Port: 1883
    • Mosquitto doesn’t need any configuration whatsoever so you don’t need to do anything once the container is up.
    • Set up Zigbee2MQTT (http://serverip:8080). It should auto-recognize your dongle and from there you can enable “Permit Join (All)” to start adding Zigbee devices. Adding devices via Zigbee2MQTT should auto-register with Home Assistant since HA is monitoring Mosquitto for events and thus there is no extra integration or setup needed in HA other than setting up MQTT.
    • Set up ZWave-JS-UI (http://serverip:8091). See minimum settings here.
    • Set up Z-Wave-JS integration in Home Assistant. Unlike Zigbee2MQTT, ZWave-JS-UI does have a dedicated integration in HA. Enable the integration via Settings > Devices and Services > Add Integration > Z-Wave. URL: ws://localhost:3000
    • [Optional] Set up Nodered, I won’t cover this, but the docker compose will start up the service.
    • [Optional] Set up InfluxDB, raising the stack does 95% of the work except for creating an API token that HA can use. So go into InfluxDB (http://serverip:8086), Load Data > API Tokens, and generate an API Token for All Access and give it a name like “homeassistant”.
    • [Optional] Set up Grafana (http://serverip:3030), and add a data source for InfluxDB.
      • URL: http://serverip:8086
      • Skip TLS Verify: enable
      • Database: homeassistant
      • User: homeassistant
      • Password: Same password that you chose in line 89 of docker-compose.yml
    • [Optional] Set up Home Assistant to send data to InfluxDB. There are a few steps here, so see the more detailed section below.

Setting up Home Assistant to send data to InfluxDB

Currently, you need to set up the Home Assistant integration with InfluxDB via the configurations.yaml file as there is no user-friendly GUI method to achieve this.

Bash
docker exec -it homeassistant /bin/bash
apk add nano
nano configurations.yaml

Add an influxdb section. See Home Assistant documentation for more info. I’m using the generic one that is below that came from the Home Assistant documentation. Save, close, then restart Home Assistant container.

Line 5 should be the IP of the server that it is running on. Ex: 192.168.1.50

Line 7 should be the API Token that you created in InfluxDB.

configuration.yaml
...
influxdb:
  api_version: 2
  ssl: false
  host: <serverip>
  port: 8086
  token: <influxdb token>
  organization: homeassistant
  bucket: homeassistant
  tags:
    source: HA
  tags_attributes:
    - friendly_name
  default_measurement: units
  exclude:
    entities:
      - zone.home
    domains:
      - persistent_notification
      - person
  include:
    domains:
      - sensor
      - binary_sensor
      - sun
    entities:
      - weather.home
...

That should be it. Post a comment if you run into any issues.

Leave a Reply

Your email address will not be published. Required fields are marked *

one × 2 =