Recently, I migrated my whole home automation setup from a group of Raspberry Pis to an Intel NUC; specifically the Intel NUC8i5BEK. Due to an increasingly larger set of devices, a single Pi for running Home Assistant and Node-RED did not cut it anymore. See my post on my hardware setup for more information.

With the introduction of the Intel Nuc to my setup, the way I configured my system also changed. Previously, I used Hass.io for managing all services. With the new NUC, I wanted to be more in control. I ended up adopting Docker and Docker Compose for my setup.

During the migration of my setup, it took quite some time to figure out the configurations for all services. In this blog post, I share the configurations I eventually came up with, and which now power my system. I now have running containers for Home Assistant, Node-RED, AppDaemon, MariaDB, VS Code, and Deconz.

Any questions about these setups? Feel free to add a question in the comments. Tips to improve it, those are very welcome too!

Table of contents

Use of the .env file

Al my configurations are pushed to Github as a way of back up. It’s not really desirable to commit secrets (passwords, tokens, etc.), so you don’t want these in your config file. Luckily, docker-compose can read these from an .env file. In all the examples below, I assume that you have a .env file with the required variables.

Note on volumes

Most of the docker containers use volumes to store persistent data. Without these volumes, all data and configuration would be lost if you restart one of the containers. Make sure to check the volumes config of each configuration block and update accordingly to your liking.

I store all my configuration (e.g., al volumes) in a central directory like ~/homeautomation-config. This directory can then be easily backed up on a remote device.

Docker compose for Home Assistant

logo-prettyCreated with Sketch.


The Home Assistant docker is the main container of my smart home setup. Most configuration is done within HA itself, so it’s a matter of spinning up the container. I use MariaDB for storing all event data, so that container needs to start first. I also make sure that my Zigbee hub is running before starting HA.

Website:
Home Assistant
ENV variables:
  • LOCAL_USER: (Optional) Map the docker user to your user id. This ensures that files can be edited without root access. Especially useful in combination with the VSCode server image.
# HomeAssistant
homeassistant:
  container_name: home-assistant
  image: homeassistant/home-assistant
  volumes:
    # Local path where your home assistant config will be stored
    - <local config path>:/config
    - /etc/localtime:/etc/localtime:ro
  restart: unless-stopped
  network_mode: host
  depends_on:
    # MariaDB is optional (only if you would like to use a different database for HA).
    - mariadb
    # Deconz is optional (only if you use the deconz Zigbee hub).
    - deconz
  user: "${LOCAL_USER}:${LOCAL_USER}"

Docker compose for Database using MariaDB

I use MariaDB as my main database for Home Assistant. HA gets its own user account to access the db.

Website:
MariaDB
ENV variables:
  • MYSQL_ROOT_PASSWORD: Root password for the service.
  • HA_MYSQL_PASSWORD: Password that home assistant will use to connect with the db.
  • LOCAL_USER: (Optional) Map the docker user to your user id. This ensures that files can be edited without root access.
# MariaDb
mariadb:
  image: mariadb/server:10.3
  container_name: mariadb
  restart: unless-stopped
  environment:
    MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
    MYSQL_DATABASE: ha_db
    MYSQL_USER: homeassistant
    MYSQL_PASSWORD: "${HA_MYSQL_PASSWORD}"
  user: "${LOCAL_USER}:${LOCAL_USER}"
  volumes:
    # Local path where the database will be stored.
    - <local db path>:/var/lib/mysql
  ports:
    - "3306:3306"

Docker compose for Zigbee hub using Deconz

To control my devices, I use the ConBee USB ZigBee hub from Dresden Elektroniks. It’s a great device with a vast list of compatible devices. Luckily, there is a Docker image that can be used to run their software. It even has support for viewing the mesh network through VNC.

Hardware:
Conbee 2 (I'm using the Conbee 1, but the v2 is slightly improved and should be bought from now on.)
Website:
Conbee 1 or Conbee 2
ENV variables:
  • VNC_PASSWORD: Password to use when connecting to the VNC server (for viewing the mesh network).
Additional notes:
  • You need to map the right USB device to the container. For the Conbee 2 the device mapping is slightly different. You can use `/dev/ttyACM0` instead of `dev/ttyUSB0`.
# Deconz
deconz:
  container_name: deconz
  image: marthoc/deconz
  restart: unless-stopped
  network_mode: host
  environment:
    # You can access Deconz at this port
    DECONZ_WEB_PORT: 8080
    DECONZ_WS_PORT: 8088

    # Set VNC_MODE to 0 to disable it completely
    DECONZ_VNC_MODE: 1
    DECONZ_VNC_PORT: 5900
    DECONZ_VNC_PASSWORD: "${VNC_PASSWORD}"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro
    # Replace <local path> with a path where all deconz config will be stored.
    - <local path>:/root/.local/share/dresden-elektronik/deCONZ
  devices:
    - "/dev/ttyUSB0:/dev/ttyUSB0"

Docker compose for Node-RED

image/svg+xml


Node-RED powers most of the automations in my smart home. After setting up the container, you can install extensions and configure the connection between Home Assistant and Node-RED.

Website:
Node-RED
ENV variables:
  • LOCAL_USER: (Optional) Map the docker user to your user id. This ensures that files can be edited without root access. Especially useful in combination with the VSCode server image.
Additional notes:
  • When the Node-RED container is running, you can install the Home Assistant extension and connect Node-RED with HA. You only have to do this once. After the initial install, all configurations and extension are saved.
  • The Home Assistant extension for Node-RED is node-red-contrib-home-assistant-websocket. You can install this extension within Node-RED by going to "Manage palette" in the menu.</a>
  # Node-RED
  nodered:
    container_name: nodered
    image: nodered/node-red
    ports:
      - "1880:1880"
    volumes:
      # Local path where all Node-RED config will be stored.
      - <local path>:/data
    depends_on:
      - homeassistant
    environment:
      TZ: "Europe/Amsterdam"
    user: "${LOCAL_USER}:${LOCAL_USER}"
    restart: unless-stopped

Docker compose for AppDaemon

AppDaemon is a great way to create small Python-based scripts that can interface with Home Assistant. AppDaemon runs in its own container and needs a “long lived access token” from HA to communicate.

Website:
AppDaemon
ENV variables:
  • SERVER_IP: URL of Home Assistant.
  • HA_APPDAEMON_KEY: Long lived access token generated in Home Assistant.
  • LOCAL_USER: (Optional) Map the docker user to your user id. This ensures that files can be edited without root access. Especially useful in combination with the VSCode server image.
appdaemon:
  container_name: appdaemon
  restart: unless-stopped
  image: acockburn/appdaemon:latest
  environment:
    HA_URL: "http://${SERVER_IP}:8123"
    TOKEN: "${HA_APPDAEMON_KEY}"
    DASH_URL: "http://${SERVER_IP}:5050"
  ports:
    - "5050:5050"
  volumes:
    # Set which local directory will contain all your app daemon configuration
    - <local config>:/conf
  depends_on:
    - homeassistant
  user: "${LOCAL_USER}:${LOCAL_USER}"

Docker compose for VS Code Server

Not technically required for Home Assistant, but Visual Studio Code Server is a great way to add a remote IDE to your setup. When the container is running, you have access to a complete IDE within your browser.

Website:
cdr/code-server
ENV variables:
  • VSCODE_PASSWORD: Password you want to use with VS Code
# Visual Studio code
vscode:
  container_name: vscode
  image: codercom/code-server:v2
  volumes:
    # Set <project dir> to the directory you want to open in VS Code.
    - <project dir>:/home/coder/project
    # <vs code config> should point to a local dir where vs code stores its data.
    - <vs code config dir>:/home/coder/.local/share/code-server
  ports:
    - "8443:8443"
  command: code-server --auth password --port 8443 --disable-telemetry /home/coder/project
  environment:
    PASSWORD: "${VSCODE_PASSWORD}"
  restart: unless-stopped

Complete docker compose file

For reference, the .env and docker-compose.yaml file:

.env

SERVER_IP= 0.0.0.0
HA_APPDAEMON_KEY=some long accces token
VSCODE_PASSWORD=password
LOCAL_USER=1000
VNC_PASSWORD=password
MYSQL_ROOT_PASSWORD=password
HA_MYSQL_PASSWORD=password

docker-compose.yaml

version: '3'
services:
  # HomeAssistant
  homeassistant:
    container_name: home-assistant
    image: homeassistant/home-assistant
    volumes:
      # Local path where your home assistant config will be stored
      - <local config path>:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    network_mode: host
    depends_on:
      # MariaDB is optional (only if you would like to use a different database for HA).
      - mariadb
      # Deconz is optional (only if you use the deconz Zigbee hub).
      - deconz
    user: "${LOCAL_USER}:${LOCAL_USER}"

  # MariaDb
  mariadb:
    image: mariadb/server:10.3
    container_name: mariadb
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
      MYSQL_DATABASE: ha_db
      MYSQL_USER: homeassistant
      MYSQL_PASSWORD: "${HA_MYSQL_PASSWORD}"
    user: "${LOCAL_USER}:${LOCAL_USER}"
    volumes:
      # Local path where the database will be stored.
      - <local db path>:/var/lib/mysql
    ports:
      - "3306:3306"

  # Deconz
  deconz:
    container_name: deconz
    image: marthoc/deconz
    restart: unless-stopped
    network_mode: host
    environment:
      # You can access Deconz at this port
      DECONZ_WEB_PORT: 8080
      DECONZ_WS_PORT: 8088

      # Set VNC_MODE to 0 to disable it completely
      DECONZ_VNC_MODE: 1
      DECONZ_VNC_PORT: 5900
      DECONZ_VNC_PASSWORD: "${VNC_PASSWORD}"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      # Replace <local path> with a path where all deconz config will be stored.
      - <local path>:/root/.local/share/dresden-elektronik/deCONZ
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"

  # Node-RED
  nodered:
    container_name: nodered
    image: nodered/node-red
    ports:
      - "1880:1880"
    volumes:
      # Local path where all Node-RED config will be stored.
      - <local path>:/data
    depends_on:
      - homeassistant
    environment:
      TZ: "Europe/Amsterdam"
    user: "${LOCAL_USER}:${LOCAL_USER}"
    restart: unless-stopped

  # AppDaemon
  appdaemon:
    container_name: appdaemon
    restart: unless-stopped
    image: acockburn/appdaemon:latest
    environment:
      HA_URL: "http://${SERVER_IP}:8123"
      TOKEN: "${HA_APPDAEMON_KEY}"
      DASH_URL: "http://${SERVER_IP}:5050"
    ports:
      - "5050:5050"
    volumes:
      # Set which local directory will contain all your app daemon configuration
      - <local config>:/conf
    depends_on:
      - homeassistant
    user: "${LOCAL_USER}:${LOCAL_USER}"

  # Visual Studio code
  vscode:
    container_name: vscode
    image: codercom/code-server:v2
    volumes:
      # Set <project dir> to the directory you want to open in VS Code.
      - <project dir>:/home/coder/project
      # <vs code config> should point to a local dir where vs code stores its data.
      - <vs code config dir>:/home/coder/.local/share/code-server
    ports:
      - "8443:8443"
    command: code-server --auth password --port 8443 --disable-telemetry /home/coder/project
    environment:
      PASSWORD: "${VSCODE_PASSWORD}"
    restart: unless-stopped