Z-Wave project: run Z-Wave JS UI in Docker and connect it to Home Assistant (with backups and hardening)

Discuss the Implementation and Development of Z-Wave Devices
Post Reply
User avatar
ZerOne
Site Admin
Posts: 216
Joined: Sun Dec 13, 2020 8:21 am

A walkthrough for running a Z-Wave controller on a separate Docker host (or Home Assistant Container/Core) rather than a Home Assistant OS add-on. Based on the Z-Wave JS UI docker-compose example and the Home Assistant Z-Wave docs as at October 2026 (Z-Wave JS UI v11.25.1, released 23 October 2026, as I write). I have not run this exact compose file for this post, so adjust to your setup and read the Z-Wave JS UI docs.

Heads up for Home Assistant OS users: the HA docs say the Z-Wave JS UI app is being phased out, because its UI is now built into the Z-Wave JS app. If you run HA OS, use the Z-Wave JS app. This project is for Container/Core installs, or for people who want the controller on a different machine.

What you need
  • A Z-Wave adapter for ANZ (see the buying guide in this forum), on a USB extension cable.
  • A Docker host that can see the stick.
  • Home Assistant with the Z-Wave integration.
Step 1: find a stable device path

Do not use /dev/ttyUSB0 or /dev/ttyACM0 because the numbering can change. The compose example says to use the /dev/serial/by-id/... path:

Code: Select all

ls -l /dev/serial/by-id/
Step 2: compose file

Based on the project's example:

Code: Select all

services:
  zwave-js-ui:
    container_name: zwave-js-ui
    image: zwavejs/zwave-js-ui:latest
    restart: always
    tty: true
    stop_signal: SIGINT
    environment:
      - SESSION_SECRET=change-me-to-a-long-random-string
      - TZ=Australia/Sydney
    devices:
      - '/dev/serial/by-id/YOUR-STICK-ID:/dev/zwave'
    volumes:
      - zwave-config:/usr/src/app/store
    ports:
      - '8091:8091'   # web interface
      - '127.0.0.1:3000:3000'   # Z-Wave JS websocket server
volumes:
  zwave-config:
    name: zwave-config
Notes:
  • Set SESSION_SECRET to your own random value; the example uses a placeholder.
  • Port 8091 is the web UI, port 3000 is the Z-Wave JS WebSocket server that Home Assistant connects to. If Home Assistant runs on a different machine you cannot bind 3000 to localhost: publish it to the LAN instead, and firewall it to the Home Assistant host only. As far as I know the WebSocket server does not require a login by default (check the docs), so treat port 3000 as trusted-network only. The 127.0.0.1 binding in the example only works if Home Assistant runs on the same host with host networking; otherwise publish it normally and firewall it.
  • Pin the image tag to a release number rather than latest once it is working, so an update does not surprise you.
  • Keep the UI and WebSocket ports off the internet. Use a VPN if you need remote access, and check the Z-Wave JS UI settings for its authentication option.

Code: Select all

docker compose up -d
Step 3: configure the controller
  • Open http://your-host:8091. In Settings, Z-Wave, set the serial port to /dev/zwave.
  • Generate the security keys (S0 and the three S2 keys) in the same section and copy them somewhere safe, such as a password manager. Losing them makes a restore or migration painful.
  • Set the RF region to ANZ if it does not match automatically.
  • In Settings, Home Assistant, enable the WS Server.
Step 4: connect Home Assistant

In Home Assistant, add the Z-Wave integration. If asked, untick the option to use the Z-Wave JS app, then enter the server URL: ws://your-docker-host:3000. Wording may differ across Home Assistant versions.

Step 5: include devices and test
  • Include devices from the Z-Wave JS UI or from Home Assistant's Z-Wave page, not from the stick's button. Use S2 where offered, and S0 only where it is the only choice, such as older door locks.
  • Once a device is in, only rebuild routes when you need to (for example after moving devices). It generates traffic, so do it overnight on a larger network and not over and over.
  • Wake battery devices (button press) so they finish their interview.
  • Some devices do not create entities: button remotes send events, so use them as automation triggers.
Step 6: backups
  • Back up the /usr/src/app/store volume. It holds the Z-Wave JS UI settings including your keys.
  • Download an NVM backup of the adapter itself (Z-Wave JS UI has a backup option) before firmware updates, migrating, or any reset.
  • Test the restore path once while nothing depends on it.
Links
Question for the group: are you running Z-Wave JS UI separately from Home Assistant, or using the built-in Z-Wave JS app, and what made you choose that? Any tips on keeping the WebSocket link reliable across hosts?
Post Reply

Return to “Z-Wave Wireless Technology”