Blog
Setting up Home Automation with Docker Compose: Home Assistant, Node-RED, and more

Setting up Home Automation with Docker Compose: Home Assistant, Node-RED, and more

(updated May 14, 2020)
Table of contents

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

Updates

14-05-2020: Updated VS Code setup.

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

Home Assistant logo

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

Conbee 2 USB Zigbee hub

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

Node-RED logo

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.
  # 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
  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:8080"
  command: code-server --auth password --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

Comments (30)

P Pablo
Hi Wouter, Thank you so much for this amazing guide! I've been hesitant to start with home automation, I was looking for an option to allow me full control over my setup, unlike ecosystems such as SmartThings, or isolated/independent third party apps. Since a long time ago, I've known that Home Assistant was the answer, but the amount of configuration required is overwhelming. I finally decided upon it, I heard some complains about performance, hence went directly for an Intel Nuc and a Conbee II. Next thing I was recommended was to prefer a docker setup over hass.io, given that would give me the chance to install Ubuntu in the Nuc at use it at its full potential, which I configured to some extent by following other guides that did not cover as much ground as yours. In all honesty, at this point, I realized that I have to get familiar with docker in order to be more proactive with the adoption of new 'add ons'. And that was precisely another surprise for me, I didn't realize these add-ons from hass.io were not going to be available with a docker installation. The more you know. I'm glad that I found your guide, one thing that I'm looking forward to and missing from the guide is connecting home assistant to the mobile companion app. How difficult do you think it might be to extend your setup with this new feature? Is it doable?
W Wouter Bulten
Hi Pablo! Thanks for the compliments! Good to hear that it was helpful to you. The hass.io/HA approach indeed has the benefit of the easy install of many add-ons. As far as I know, it's also using docker in the backend but with a nice interface on top. I wanted more control over the services, so I went the custom route through my own docker setup (described in this post). This approach brings more control over the services and everything is a bit less tied into HA itself. Also, it allows for the installation of a lot more services outside of the HA add-on list. The downside is that it takes a bit more work/expertise when installing and maintaining. It depends on the use case and personal preferences which approach would be best suited. Regarding your question: You would like to connect your HA instance to the Android/iOS companion app? You don't need to do anything specific for that. Both the Hassio/HA and HA Core approach will work. I also use the apps; it was a matter of installing them, and then then they auto-detected my HA instance. Do you have any problems with the companion apps and your setup?
P Pablo
Hi Woulter, Thanks for the prompt reply. In my initial setup, it didn't automatically detect any instance as advertise, I chose the option to enter the URL to the instance manually and understood that I have to use DuckDNS in combination with other service for SSL in order to be able to access it remotely (As I don't have a fix IP address or own a domain name). At this point, I'm implementing my instance using your guide. I'll let you know how that goes. :) I wonder if you're familiar with remote access in the companion app, and can provide some guidance.
W Wouter Bulten
Hi Pablo, Unfortunately, I don't have experience with opening up HA to the outside world. I use [Home Assistant Cloud](https://www.nabucasa.com/) instead. With that you don't need to have a fixed ip or domain name. If you want an easy solution that works, I can definitely recommend it!
P Pablo
Hi Wouter, Finally was able to set everything up. I went with Home Assistant Cloud, on the trial right now, and it's working great with the Companion App. I'll definitely upgrade after the trial is over. Rather pay for this option than opening ports in my router. Also, it is a convenient way to support the community. Thanks again, really appreciate your help!
R René
Hello Wouter, What a great tutorial which i also will try to setup!! Running Domoticz on a pi3B at the moment, but also looking for more power.
W Wouter Bulten
Thanks René! Good luck with your setup :)
R René
Wouter, Which operating system are you running?
W Wouter Bulten
I'm running Ubuntu server on my NUC. Regards, Wouter
A Adam Sherman
Great guide! I have most of this running on top of Balena, in a Pi 4. Do you know to configure HA soit shows add-on UIs, like Node-RED, in its sidebar? (Looks like it proxies to the other containers.) Thanks, A.
W Wouter Bulten
Hi Adam, thanks! Would this be something you are looking for? https://www.home-assistant.io/integrations/panel_iframe/ Then you can add your Node-RED instance to the sidebar. Regards, Wouter
A Adam Sherman
Yeah, other than the restrictions of using an iframe, that looks good. Thanks! Do you know if that is how the supported Home Assistant setup works?
W Wouter Bulten
Hi Adam, you mean if you run the Home Assistant OS? I'm not completely sure as I don't have experience with that setup, but I imagine it's at least something similar.
A Adam Sherman
I got it working. Figuring out how to get things to proxy is a project on the list, then. Thanks for your help!
L Luca Marciò
Hi! Hope you had great Xmas holidays and you are safe and sound (hard times also here in Italy). I'm stepping into HA and I'm looking for the easiest way to test it starting from my test hardware: an old PC with i3@3,10GHz, 4 GB ram and 120 GB hdd. I'd also like to have a media server (to watch movies on my TVs) and a file server (to share files) running beside HA. As a first test I installed Proxmox on my PC with HA Core on it but it seemed too difficult to me. As a second test I installed Ubuntu Desktop on my PC and HA Core inside Docker: it seemed more confortable to me but the Core version of HA has no add-ons. Now I'm stuck make my decision between going on with a supported HA installation or install HA Supervised on Docker on Ubuntu desktop... Which way do you suggest me considering my needs (HA+media server+ file server)? Thanks and congrats for your website. Greetings from Italy. Luca.
W Wouter Bulten
Hi Luca, what best suits you of course depends on your own personal preferences. It's hard to give a definitive answer ;) I can give my view on the Docker setup: With Docker you have all the freedom to install other services, including things that don't have a HA add-on. All the add-ons from HA run on Docker, so there is often also a very simple docker-compose snippet readily available to install it alongside HA Core. Of course, using HA OS with its add-ons simplifies this a bit as you can install and manage them using a UI. For this, you could also check out Portainer. It gives you an interface to manage your running docker containers. Secondly, HA Core does not "take over" your machine, but you just install HA as one of the services that run on it. This means that the services are not tied to each other. You could shutdown HA but your file/media server would still run. Finally, I also picked Docker because I wanted to get a bit more experienced with a container-based setup. If you use HA OS, this is all done for you. Doing it myself was a nice learning experience :) To summarize: probably all approaches would work in the end. Whatever suits you best depends on your preferences and experience. Go for HA OS if you want easy and (potentially) less maintenance; go for Docker for freedom and more control. Good luck!
L Luca Marciò
Hi Wouter! What about installing HA Supervised (to have all the add-ons) on docker on my Ubuntu PC? I know that is no more officially supported now but what kind of problem could this bring to the final user? Another question, please: since I have other two PCs with Windows, looking at the file/media server, do you think it’s a good idea to install Docker (with HA on it) on a Windows environment instead of Ubuntu server? Thanks for supporting me again. Stay safe. Luca.
W Wouter Bulten
You could also do that, but I don't have experience with it myself. I guess that it's maybe a bit less maintenance, but could also be trickier to set up (just guessing here, I only use my Docker setup on Ubuntu Server). Sorry that I can't help you further on that. Regarding your other question: If everything you want to install works on Windows, you could also try that. In general, I don't think many people run HA on Windows. There are probably also more services you can run on a Unix based system, so then you would need to have a VirtualBox setup. I would probably go for Ubuntu (server). Your file/media server should work fine with the other Windows devices.
K Kiat Huang
Hi Wouter, Greetings from England! This is an incredibly well-written and useful guide by you on home automation. Like you, I've gravitated to Home Assistant and Node-Red, in my case having persevered with monolithic OpenHAB, zigbe2mqtt, then Home Assistant wIth InfluxDB, Grafana, and tried out Zigbee CC2531, Raspbee and Sonoff bridges - all learning as I went. But all were simply not both stable and easy to configure and there was too much having to get into Zigbee internals. It all did not seem modular and replicable enough - and I think you've hit the right balance of modularity and simplicity for what is a complicated task of building and maintaining a huge variety of devices and technologies. So thanks! I'll be following your methods and try to build something that's easy to use, resilient and appliance like as I can get.
W Wouter Bulten
Hi Kiat, Thanks for the compliments. I've been traversing a similar path: from a single Pi using 2 lightbulbs to a more elaborate system using Docker. Great to hear that the guide helped! Regards, Wouter
D David
Great write up. Other than some minor tweaks, I’ll be largely reusing your code, which is much appreciated. A couple of questions: What other docker containers do you use related to home automation, and why? I find some containers don’t like to play nice with each other, so I find myself still keeping the pi’s around. Any thoughts on this? Room assistant? Portainer?
W Wouter Bulten
Hi David, Thanks! Not much else actually. Besides the above, I do have AdGuard, Portainer, and Glances running. I don't do a lot through Portainer though; instead, I've added some buttons to my HA control panel to start/stop containers if needed. So far I haven't experienced a lot of problems with containers not working together, after solving some of the initial ip/port binding problems. I hope that answers your questions!
G Greg
I'm stuck here : pi@portainer:/opt/hass $ sudo docker-compose up -d ERROR: Named volume ":/var/lib/mysql:rw" is used in service "mariadb" but no declaration was found in the volumes section.
W Wouter Bulten
Hi Greg, what did you use as your local path in the config? It looks like you used a named volume but that's not what I used in the config. Maybe an error in the mapping caused this. Did you replace `` with a proper path? Could you share the mariadb block?
G Greg
Thank you for your response, in fact i did not changed anything, could you share example, I'm not so clever it seems...
W Wouter Bulten
Hi Greg, In this part: ``` volumes: # Local path where the database will be stored. - :/var/lib/mysql ``` You need to replace `` with a path on your machine. So it could be something like: ``` volumes: - /home/wouterbulten/homeautomation/db:/var/lib/mysql ``` Did you set that correctly? Regards, Wouter
N Niels Jansen
Hi Wouter, first, thanks for the nice explanation! I was running home assistant on a vm on ubuntu but it was crashing every 3 days. Now I have setup ubuntu server with the docker containers and I have much more control and its stable! However I can't get visual studio to work properly. It can't save any files, because there is a permissions issue. It says "error vscode is not running Error: vscode is not running" in the console, but it is runing, it just can't save the files. "Failed to save 'configuration.yaml': Unable to write file 'vscode-remote://192.168.2.109:8443/home/coder/project/homeassistant/configuration.yaml' (NoPermissions (FileSystemError): Error: EACCES: permission denied, open '/home/coder/project/homeassistant/configuration.yaml')"
W Wouter Bulten
Hi Niels, it seems to be that the user running the VSCode container does not have the rights to edit the files of your HA configuration. This is always a bit tricky in cross-container setups. I would start with checking if you can edit the files yourself outside docker (through command line) and then maybe try to edit them from the VSCode docker.
D Derek Molloy
Thanks for this great guide. Please note that you need to remove the line: user: "${LOCAL_USER}:${LOCAL_USER}" From the Home Assistant settings to use the latest versions of HA otherwise you get the following errors: [s6-init] making user provided files available at /var/run/s6/etc...exited 0. s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/home-assistant/run: Operation not permitted s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/home-assistant/run: Operation not permitted s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/home-assistant/finish: Operation not permitted s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/home-assistant/finish: Operation not permitted [s6-init] ensuring user provided files have correct perms...exited 0. [fix-attrs.d] applying ownership & permissions fixes... [fix-attrs.d] done. [cont-init.d] executing container initialization scripts... [cont-init.d] done. [services.d] starting services s6-supervise (child): fatal: unable to exec run: Permission denied s6-supervise home-assistant: warning: unable to spawn ./run - waiting 10 seconds The configuration that worked for me is: version: '3' services: # HomeAssistant homeassistant: container_name: home-assistant image: homeassistant/home-assistant:stable volumes: # Local path where your home assistant config will be stored - /home/xxx/HomeAssistant:/config - /etc/localtime:/etc/localtime:ro - /home/xxx/HomeAssistant/shared:/shared restart: unless-stopped # network_mode: host ports: - "8123:8123" privileged: true depends_on: # MariaDB is optional ... - mariadb environment: - PUID=${LOCAL_USER} - PGID=${LOCAL_USER} - UMASK=007 - TZ=Europe/Dublin
W Wouter Bulten
Great to hear that you got it working!

Adding new comments is no longer possible. If you have a question or remark, please reach out via the contact page.

Copyright © 2026 Wouter Bulten

I may not have gone where I intended to go, but I think I have ended up where I needed to be.

— Douglas Adams, The Long Dark Tea-Time of the Soul

Colophon & disclaimer