Home Assistant on Synology DSM (Docker, DuckDNS, Let's Encrypt, Reverse Proxy, Firewall, zWave, Node-Red, MQQT)

The following use a much as possible of the DSM components to ensure your Home-Assistant configuration can be pretty much vanilla and not Synology Specific. Some of these can be done within Home-Assistant, but I’ve found this to be the most compatible with other components.


Phase 1 - Setting up the images

Step 1.1) Setup the file structures
On my Synology NAS I have created the following folder structure via “File Station”

+-- MQTT
|   +-- config
|   +-- data
|   +-- log
+-- Node-RED
+-- Home Assistant

Step 1.2) Install Docker
Package Center > Search for “Docker” and install it

Step 1.3) Download and configure Docker Images
If you don’t use z-Wave, you only need to follow step 1.3.1 and 1.3.2.
If you do have a z-wave stick plugged into your Synology, ensure you have enabled the SSH Service (see: https://www.synology.com/en-global/knowledgebase/SRM/help/SRM/RouterApp/admin_services#t1_1) and follow only 1.3.3 - Advance users

Step 1.3.1) Download Images
In your DSM go to:
Docker > Registry > Insert Keyword (found below) > Search > [Select the image] > Download


  • exlipse-mosquitto:latest


  • nodered/node-red-docker:v8


  • homeassistant/home-assistant:latest

Ensure you downloaded these:

Step 1.3.2) Configure Images
Select the Image in the Image tab > Launch > Advanced Settings:


  • Advanced Settings
    [X] Enable auto-restart
  • Volume (File/Folder Mount Path Read-Only)
    • /volume1/Configuration/MQTT/config /mosquitto/config/
    • /volume1/Configuration/MQTT/data /mosquitto/data
    • /volume1/Configuration/MQTT/log /mosquitto/log
    • /etc/localtime /etc/localtime [X]
    • /etc/hosts /etc/hosts [X]
  • Network
    • [X] Use the same network as Docker Host
  • [Apply] > [Next] > [Apply]


  • Volume (File/Folder Mount Path Read-Only)
    • /volume1/Configuration/Node-RED /data
    • /etc/localtime /etc/localtime [X]
    • /etc/hosts /etc/hosts [X]
  • Network
    • [X] Use the same network as Docker Host
  • [Apply] > [Next] > [Apply]


  • Volume (File/Folder Mount Path Read-Only)
    • /volume1/Configuration/Home Assistant /config
    • /etc/localtime /etc/localtime [X]
    • /etc/hosts /etc/hosts [X]
  • Network
    • [X] Use the same network as Docker Host
  • [Apply] > [Next] > [Apply]

Also refer to: https://www.home-assistant.io/docs/installation/docker/#synology-nas

Step 1.3.3) Advanced users
If you don’t want to do steps 1.3.1 and 1.3.2 above manually and have set up SSH access to your Synology, you can create a docker file(s) and execute sudo docker-compose up -d in the same directory as your docker-compose.yml directory
This also gives you access to mount the USB from your NAS to the docker image
Generally, these files will all be in one file, I have however broken this down in case you planned to follow step 1.3.1 and 1.3.2 above for MQTT and Node-Red, and only home assistant from the command line.

Create the following files

MQTT docker-compose.yml

version: '3'
    container_name: eclipse-mosquitto
    image: eclipse-mosquitto:latest
      - /volume1/Configuration/MQTT/config:/mosquitto/config/
      - /volume1/Configuration/MQTT/data:/mosquitto/data
      - /volume1/Configuration/MQTT/log:/mosquitto/log
      - /etc/localtime:/etc/localtime:ro
      - /etc/hosts:/etc/hosts:ro
    restart: unless-stopped
    network_mode: host

Node-Red docker-compose.yml

version: '3'
    container_name: mynodered
    image: nodered/node-red-docker:v8
      - /volume1/Configuration/Node-RED:/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/hosts:/etc/hosts:ro
    restart: unless-stopped
    network_mode: host

If you do not use a zwaveusb, exclude the “devices” section below
If you are using zwaveusb, confirm that the USB is indeed on /dev /ttyACM0 (execute lsusb -i -U | grep /tty.* --color to see. Mine shows tty/ttyACM0). If it is different, update the devices section below
this will mount it on the dockers /zwaveusbstick which is currently the default location when trying to add zWave via Hass > Configuration > Integrations > Z-Wave > Configure
Also refer to: https://www.home-assistant.io/components/zwave/

Home-Assistant docker-compose.yml

version: '3'
    container_name: home-assistant
    image: homeassistant/home-assistant
      - /volume1/Configuration/Home Assistant:/config
      - /etc/localtime:/etc/localtime:ro
      - /etc/hosts:/etc/hosts:ro
      - /dev/ttyACM0:/zwaveusbstick
    restart: unless-stopped
    network_mode: host

Create the above mentioned files (they have the same name, so have to be in different folders), then SSH in, go to that directly, and execute:
sudo docker-compose up -d” in each of the directories where you created these files

Everything should now be running, you can now configure as you would normally

Phase 2 Basic Configuration

Step 2.1) Configure MQTT
setup /volume1/Configuration/MQTT/config/mosquitto.conf

Step 2.2) Configure Node-Red
setup /volume1/Configuration/Node-RED/settings.js

Step 2.3) Configure Home-Assistant
setup /volume1/Configuration/Home\ Assistant/configuration.yaml

Phase 3 External Access
Step 3.1) Setup Dynamic DNS / Duck DNS
Setup your Dynamic DNS of choice. Showing how to do that with DuckDNS
Create an account in https://www.duckdns.org/ and create a
In your DSM go to:
Control Panel > External Access > DDNS

  • Customize
    • Service Provider: duckdns
    • Query URL: http://www.duckdns.org/update?domains=__HOSTNAME__&token=__PASSWORD__&ip=__MYIP__
    • [Save]
  • Add
    • Service Provider: *duckdns
    • Hostname: <domain>
    • Username/Email: <account>
    • Password/Key: <token>

Step 3.2) Reverse Proxy
Setup Reverse Proxy for Home-Assistant
This will offload the SSL to the DSM so that internal components (such as konnected.io) can communicate via HTTP, while external components (such as google assistant) can communicate via HTTPS

In your DSM go to:
Control Panel > Application Portal > Reverse Proxy > Create

  • General
    • Description: Home Assistant Reverse Proxy
    • Source:
      • Protocol: HTTPS
      • Hostname: .duckdns.org
      • Port: 8443
    • Destiniation
      • Protocol: HTTP
      • Hostname: <local hostname/IP>
      • Port: 8123
  • Customer Header
    • [Create] > WebSocket
  • Advanced Settings
    • Proxy read timeout: 86400

Also refer to: https://www.home-assistant.io/docs/ecosystem/synology/

Step 3.3) Firewall
Setup a firewall to only allow the IPs you want to access Home assistant
In your DSM go to:
Control Panel > Security > Firewall

  • General
    • [X] Enable firewall
  • Firewall Profile
    • Edit Rules - Setup your required rules here. Sample rules for Google Assistant, and Web Station for Let’s Encrypt
      (Enabled Ports [built-in app] Protocol Source IP [Specific IP / IP Range])
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Reverse proxy TCP -
      • [X] Web Station (80) TCP All

Step 3.4) SSL Certificate
Ensure you have set up your external port 80 to be forwarded to your internal port 80 (i.e. DSM’s web server, NOT home-assistant) on your router.
This is only required for creating and renewing the certificate, once you are done, you can remove this forwarded port until renew time.

In your DSM go to:

  • Control Panel > Security > Certificate

    • Add > Add > Add a new certificate > Get a certificate from Left Encrypt
      • Domain name: .duckdns.org
      • Email:
      • Subject Alternative Name: .duckdns.org
  • Control Panel > Security > Certificate

    • Configure (Service Certificate) - Associate the newly created certificate to the reverse proxy you created earlier
      • .duckdns.org:8443 .duckdns.org
      • [OK]

Step 3.4) Port forwarding
To access home-assistant via HTTPS (reverse proxy), you need to forward a port to that

  • Public port 8443 to :8443

To create/renew Let’s encrypt certificates

  • Public port 80 to :80

Greate guide, made my transition to running docker on my Synology so much smoother!

Tip: If you use port 443 instead of port 8443 in the Reverse Proxy settings in step 3.2 and add port 443 in your firewall settings (see below), you access your duckdns domain without a port number name.duckdns.org instead of name.duckdns.org:8443.

Add port 443 to firewall settings
control panel > security > firewall > edit rules > create > Select from a list of built-in applications > Check [https, reverse proxy]

1 Like

Thanks for posting @shark711, very comprehensive! Can I check a few things with your post?

Regarding Step 1.3.2), do you have to mount “/etc/localtime” and “/etc/hosts”… or can you skip this?

For Step 2.1) and step 2.2), do you have to provide a config file manually? or will one appear thay you edit? My Docker containers in Synology keeps restarting saying it cannot find files

Error log for NODERED:
[error] Failed to start server:
Error: EACCES: permission denied, mkdir ‘/data/lib’

Error log for Mosquitto
Error: Unable to open log file /mosquitto/log/mosquitto.log for writing
Error found at /mosquitto/config/mosquitto.conf:0.
Error: Unable to open configuration file.
Error: Unable to open config file /mosquitto/config/mosquitto.conf

Any tips on configuring these programs for Home Assistant? Any advise would be greatly appreciated :blush:

Can someone please post a sample mosquitto.conf file that should be uploaded to MQTT config directory?

Try this maybe

# Config file for mosquitto
# Write process id to a file. Default is a blank string which means
# a pid file shouldn't be written.
# This should be set to /var/run/mosquitto.pid if mosquitto is
# being run automatically on boot with an init script and
# start-stop-daemon or similar.
pid_file /var/run/mosquitto.pid
# When run as root, drop privileges to this user and its primary
# group.
# Leave blank to stay as root, but this is not recommended.
# If run as a non-root user, this setting has no effect.
# Note that on Windows this has no effect and so mosquitto should
# be started by the user you wish it to run as.
user mosquitto

# =================================================================
# Default listener
# =================================================================

# IP address/hostname to bind the default listener to. If not
# given, the default listener will not be bound to a specific
# address and so will be accessible to all network interfaces.
# bind_address ip-address/host name

# Port to use for the default listener.
port 8883

# =================================================================
# Persistence
# =================================================================

# Save persistent message data to disk (true/false).
# This saves information about all messages, including
# subscriptions, currently in-flight messages and retained
# messages.
# retained_persistence is a synonym for this option.
persistence true

# The filename to use for the persistent database, not including
# the path.
#persistence_file mosquitto.db

# Location for persistent database. Must include trailing /
# Default is an empty string (current directory).
# Set to e.g. /var/lib/mosquitto/ if running as a proper service on Linux or
# similar.
persistence_location /mosquitto/data/

# =================================================================
# Logging
# =================================================================

# Places to log to. Use multiple log_dest lines for multiple
# logging destinations.
# Possible destinations are: stdout stderr syslog topic file
# stdout and stderr log to the console on the named output.
# syslog uses the userspace syslog facility which usually ends up
# in /var/log/messages or similar.
# topic logs to the broker topic '$SYS/broker/log/<severity>',
# where severity is one of D, E, W, N, I, M which are debug, error,
# warning, notice, information and message. Message type severity is used by
# the subscribe/unsubscribe log_types and publishes log messages to
# $SYS/broker/log/M/susbcribe or $SYS/broker/log/M/unsubscribe.
# The file destination requires an additional parameter which is the file to be
# logged to, e.g. "log_dest file /var/log/mosquitto.log". The file will be
# closed and reopened when the broker receives a HUP signal. Only a single file
# destination may be configured.
# Note that if the broker is running as a Windows service it will default to
# "log_dest none" and neither stdout nor stderr logging is available.
# Use "log_dest none" if you wish to disable logging.
log_dest file /mosquitto/log/mosquitto.log
log_dest stderr

# =================================================================
# Security
# =================================================================

# If set, only clients that have a matching prefix on their
# clientid will be allowed to connect to the broker. By default,
# all clients may connect.
# For example, setting "secure-" here would mean a client "secure-
# client" could connect but another with clientid "mqtt" couldn't.
# Boolean value that determines whether clients that connect
# without providing a username are allowed to connect. If set to
# false then a password file should be created (see the
# password_file option) to control authenticated client access.
# Defaults to true.
allow_anonymous false

# -----------------------------------------------------------------
# Default authentication and topic access control
# -----------------------------------------------------------------

# Control access to the broker using a password file. This file can be
# generated using the mosquitto_passwd utility. If TLS support is not compiled
# into mosquitto (it is recommended that TLS support should be included) then
# plain text passwords are used, in which case the file should be a text file
# with lines in the format:
# username:password
# The password (and colon) may be omitted if desired, although this
# offers very little in the way of security.
# See the TLS client require_certificate and use_identity_as_username options
# for alternative authentication options.
password_file /etc/mosquitto/passwd

# =================================================================
# External config files
# =================================================================

# External configuration files may be included by using the
# include_dir option. This defines a directory that will be searched
# for config files. All files that end in '.conf' will be loaded as
# a configuration file. It is best to have this as the last option
# in the main file. This option will only be processed from the main
# configuration file. The directory specified must not contain the
# main configuration file.
include_dir /mosquitto/config/conf.d
1 Like

Optional, this is just to simplify it, as you change you DSM timezone this should auto sync

Not sure why, but it seems your user does not have the permissions to create these folders and files

Ensure the directories (volumes) listed in docker-compose.yml can be modified by the user home assistant is running as. Also ensure you do not set it as Read Only
This is what I get when I run an ls command in the SSH terminal

ls -al /volume1/Configuration/
total 20
drwxrwxrwx+ 1 root  root    112 Mar 30 23:54 .
drwxr-xr-x  1 root  root    332 May  2 10:14 ..
-rwxrwxrwx+ 1 admin users 16388 May  2 19:10 .DS_Store
drwxrwxrwx+ 1 root  root     52 May  2 10:14 @eaDir
drwxrwxrwx+ 1 admin users   604 May  2 19:22 Home Assistant
drwxrwxrwx  1 admin users    82 Jun 21  2018 MQTT
drwxrwxrwx  1 admin users   360 Mar 30 11:39 Node-RED

Or from DSM

not sure if yours is perhaps set to root… If you set up the structures as per step 1.1, this should just work.


Will check it out… thanks for your help :slight_smile:

I configured my homeassistant on Docker as instructed. But when entering the url I get the message it is not a secure connection. Do I have to change something in my config ?

Solved : What I did not new I had to add in DSM-certificate that the certificate was provided by Letsencrypt.
Synology automatically filled in it was provided by Synology

How to add grafana to this, so the shared url’s use https too ?

I read that I had to modify these lines in grafana.ini

protocol = https

#https certs &amp; key file
cert_file = /etc/letsencrypt/live/<your dns address>/fullchain.pem
cert_key = /etc/letsencrypt/live/<your dns address>/privkey.pem

but the grafana container won’t restart then.

Awesome, really helpful guide ! Thanks !!!

Did you have to do anything else to get this working? I can’t use port 443 because the built in nginx already redirects port 443 to DSM’s https port 5001.

Great guide @shark711 !

It really helped me with my own setup but I have two questions regarding the firewall, step 3.3:

  1. In the screenshot of firewall rules there is a rule for Reverse Proxy with source IP which is not mentioned in the text. What’s this? Something worth adding?

  2. Does the firewall block everything else by default? Or do I need to add a rule so that all other IPs are blocked? The way I see it we’ve added several allow-rules but they’re not of any value as implcicitly everything else is also allowed… but please correct me on this if I’m wrong.

Hey, I did this, but with Port 443 and my own domain, which points to a duckdns url (had this working before with a raspberry pi), but when going to https://sub.domain.de I get a synology message saying:

Sorry, the page you are looking for is not found.

Somehow the traffic is not routed to 8123 it seems?

Thanks for posting this thread. I almost gave up and installed a VM and hass.io because I was unable to get SSL working until I found this thread.

I’'m trying to mount the /etc/hosts and /etc/localtime file in step 1.3.2 but I am running into some problems.
I’ve created symbolic links to both in /volume1/configuration/etc and can see them in using ssh, they have rw- r-- r-- permissions. I cannot select them in docker and cannot see them in File Station, does anyone know what I’m missing?

Yes the firewall will block everything else

I have updated this setup with support for wildcard certificates which I have described in this post: