From 3dc7fd4c88a9d586c51ad266f2a738dcc227b378 Mon Sep 17 00:00:00 2001
From: Nerivec <62446222+Nerivec@users.noreply.github.com>
Date: Fri, 28 Nov 2025 19:37:08 +0100
Subject: [PATCH] feat!: migrate regular add-on to new builder
---
.github/workflows/ci.yml | 110 ------------------
.github/workflows/release.yml | 38 ------
.gitignore | 3 -
README.md | 38 +++---
common/Dockerfile | 57 ---------
common/build.yaml | 3 -
common/local_build.sh | 8 --
common/rootfs/docker-entrypoint.sh | 104 -----------------
zigbee2mqtt/CHANGELOG.md | 11 ++
zigbee2mqtt/DOCS.md | 80 +------------
zigbee2mqtt/Dockerfile | 38 ++++++
zigbee2mqtt/README.md | 5 +-
zigbee2mqtt/build.yaml | 11 ++
zigbee2mqtt/config.json | 90 --------------
zigbee2mqtt/config.yaml | 49 ++++++++
.../s6-rc.d/user/contents.d/zigbee2mqtt | 0
.../contents.d/zigbee2mqtt-migrate-config | 0
.../dependencies.d/base | 0
.../s6-rc.d/zigbee2mqtt-migrate-config/type | 1 +
.../s6-rc.d/zigbee2mqtt-migrate-config/up | 1 +
.../dependencies.d/zigbee2mqtt-migrate-config | 0
.../etc/s6-overlay/s6-rc.d/zigbee2mqtt/finish | 28 +++++
.../etc/s6-overlay/s6-rc.d/zigbee2mqtt/run | 93 +++++++++++++++
.../etc/s6-overlay/s6-rc.d/zigbee2mqtt/type | 1 +
.../scripts/zigbee2mqtt-migrate-config.sh | 94 +++++++++++++++
zigbee2mqtt/translations/en.yaml | 44 +++++++
26 files changed, 393 insertions(+), 514 deletions(-)
delete mode 100644 .github/workflows/ci.yml
delete mode 100644 .github/workflows/release.yml
delete mode 100644 common/Dockerfile
delete mode 100644 common/build.yaml
delete mode 100755 common/local_build.sh
delete mode 100755 common/rootfs/docker-entrypoint.sh
create mode 100644 zigbee2mqtt/Dockerfile
create mode 100644 zigbee2mqtt/build.yaml
delete mode 100644 zigbee2mqtt/config.json
create mode 100644 zigbee2mqtt/config.yaml
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt-migrate-config
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/dependencies.d/base
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/type
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/up
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/dependencies.d/zigbee2mqtt-migrate-config
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/finish
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/run
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/type
create mode 100644 zigbee2mqtt/rootfs/etc/s6-overlay/scripts/zigbee2mqtt-migrate-config.sh
create mode 100644 zigbee2mqtt/translations/en.yaml
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index 933839970..000000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,110 +0,0 @@
-name: CI
-
-on:
- push:
- pull_request:
- workflow_dispatch:
- inputs:
- type:
- description: 'Type (edge/proxy)'
- default: 'edge'
- required: true
-
-jobs:
- variables:
- runs-on: ubuntu-latest
- outputs:
- ARCH_LIST: ${{ env.ARCH_LIST }}
- ADDON_LIST: ${{ env.ADDON_LIST }}
- BUILD_ARGS: ${{ env.BUILD_ARGS }}
- steps:
- - uses: actions/checkout@v3
-
- - name: "ARGS: default"
- run: |
- echo "ADDON_LIST=['zigbee2mqtt', 'zigbee2mqtt-edge']" >> $GITHUB_ENV
- echo "BUILD_ARGS=--no-latest --test" >> $GITHUB_ENV
- - name: "ARGS: zigbee2mqtt-proxy" # Build of addon proxy version
- if: github.ref == 'refs/heads/master' && (github.event_name == 'workflow_dispatch' && github.event.inputs.type == 'proxy')
- run: |
- echo "ADDON_LIST=['zigbee2mqtt-proxy']" >> $GITHUB_ENV
- echo "BUILD_ARGS=--no-cache" >> $GITHUB_ENV
- - name: "ARGS: zigbee2mqtt-edge" # Build of addon edge version
- if: github.ref == 'refs/heads/master' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.type == 'edge'))
- run: |
- echo "ADDON_LIST=['zigbee2mqtt-edge']" >> $GITHUB_ENV
- echo "BUILD_ARGS=--no-cache" >> $GITHUB_ENV
- - name: "ARGS: zigbee2mqtt" # Build of addon release version
- if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'push'
- run: |
- echo "ADDON_LIST=['zigbee2mqtt']" >> $GITHUB_ENV
- echo "BUILD_ARGS=--no-cache --docker-hub-check" >> $GITHUB_ENV
-
- - name: Determine arch
- id: determine_arch
- run: |
- ARCH_LIST=$(jq -r -c '.arch' ./${{ fromJSON(env.ADDON_LIST)[0] }}/config.json)
- echo "Found the following arches: $ARCH_LIST"
- echo "ARCH_LIST=$ARCH_LIST" >> $GITHUB_ENV
-
- build:
- runs-on: ubuntu-latest
- needs: variables
- env:
- BUILD_ARGS: ${{needs.variables.outputs.BUILD_ARGS}}
- strategy:
- matrix:
- arch: ${{fromJSON(needs.variables.outputs.ARCH_LIST)}}
- addon: ${{fromJSON(needs.variables.outputs.ADDON_LIST)}}
- steps:
- - uses: actions/checkout@v3
-
- - name: Log in to docker.io
- if: (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
- uses: docker/login-action@v3
- with:
- username: koenkk
- password: ${{ secrets.DOCKER_KEY }}
-
- - name: Log in to ghcr.io
- if: (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: koenkk
- password: ${{ secrets.GH_TOKEN }}
-
- - name: Prepare data folder
- run: |
- if [ "${{ matrix.addon }}" != "zigbee2mqtt-proxy" ]; then
- cp -R common/rootfs ${{ matrix.addon }}
- cp common/Dockerfile ${{ matrix.addon }}
- fi
- cp common/build.yaml ${{ matrix.addon }}
-
- - name: Build
- uses: home-assistant/builder@master
- # Note: if running without `--test`, image is pushed to docker.io
- with:
- args: |
- --${{ matrix.arch }} \
- --target ${{ matrix.addon }} \
- ${{ env.BUILD_ARGS }}
-
- # Keep pushing to docker.io as it is unclear how
- # HA handles config.json updates (especially for the unversioned edge)
- - name: Push to docker.io
- if: (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')) && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
- run: |
- CONFIG_IMAGE=$(cat ${{ matrix.addon }}/config.json | jq -r '.image | sub("{arch}"; "${{ matrix.arch }}")')
- CONFIG_VERSION=$(cat ${{ matrix.addon }}/config.json | jq -r .version)
-
- VERSIONS=("latest" "$CONFIG_VERSION")
- for VERSION in "${VERSIONS[@]}"; do
- GHCR_IMAGE="$CONFIG_IMAGE:$CONFIG_VERSION"
- DOCKER_IO_IMAGE=$(echo "$GHCR_IMAGE" | sed 's|ghcr\.io\/||')
- echo "Push: $GHCR_IMAGE -> $DOCKER_IO_IMAGE"
- docker pull $GHCR_IMAGE
- docker tag $GHCR_IMAGE $DOCKER_IO_IMAGE
- docker push $DOCKER_IO_IMAGE
- done
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 28dcbd5d9..000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-on:
- repository_dispatch:
- types: release
-
-name: Release
-
-permissions: {}
-jobs:
- release:
- permissions:
- contents: write
- pull-requests: write
-
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- ref: master
- token: ${{ secrets.GH_TOKEN }}
- - name: Set variables
- id: version
- run: |
- echo "addon=${{ github.event.client_payload.version }}" >> "$GITHUB_OUTPUT"
- echo "z2m=$(echo "${{ github.event.client_payload.version }}" | cut -d - -f 1)" >> "$GITHUB_OUTPUT"
- - name: Set version and update release
- run: |
- jq '.version = "${{ steps.version.outputs.addon }}"' zigbee2mqtt/config.json > zigbee2mqtt/config.json.tmp
- mv zigbee2mqtt/config.json.tmp zigbee2mqtt/config.json
- echo -e "## ${{ steps.version.outputs.addon }}\n- Updated Zigbee2MQTT to version [\`${{ steps.version.outputs.z2m }}\`](https://github.com/Koenkk/zigbee2mqtt/releases/tag/${{ steps.version.outputs.z2m }})\n" | cat - zigbee2mqtt/CHANGELOG.md > zigbee2mqtt/CHANGELOG.md.tmp
- mv zigbee2mqtt/CHANGELOG.md.tmp zigbee2mqtt/CHANGELOG.md
- - uses: stefanzweifel/git-auto-commit-action@v5
- with:
- commit_message: "v${{ steps.version.outputs.addon }}"
- - uses: ncipollo/release-action@v1
- with:
- tag: "v${{ steps.version.outputs.addon }}"
- body: "- Updated Zigbee2MQTT to version [`${{ steps.version.outputs.z2m }}`](https://github.com/Koenkk/zigbee2mqtt/releases/tag/${{ steps.version.outputs.z2m }})"
- token: ${{secrets.GH_TOKEN}}
diff --git a/.gitignore b/.gitignore
index 2b8952585..b03ce4553 100644
--- a/.gitignore
+++ b/.gitignore
@@ -108,9 +108,6 @@ venv.bak/
secrets.json
-zigbee2mqtt/rootfs
-zigbee2mqtt/Dockerfile
-zigbee2mqtt/build.yaml
zigbee2mqtt-edge/rootfs
zigbee2mqtt-edge/Dockerfile
zigbee2mqtt-edge/build.yaml
diff --git a/README.md b/README.md
index 1976559dc..f4c71e079 100644
--- a/README.md
+++ b/README.md
@@ -2,37 +2,31 @@
-
-
-
Official Zigbee2MQTT Home Assistant add-on
+[](https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/actions?query=workflow%3ACI)
+[](https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/releases)
+[](https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/stargazers)
+[](https://discord.gg/dadfWYE)
+
> [!CAUTION]
> If you're using a Raspberry Pi, ensure you have at least a Raspberry Pi 4, as running it on a Raspberry Pi 3 may cause instability due to its limited resources.
-## Installation
+## Installing this repository in your add-on store
-1. If you don't have an MQTT broker yet; in Home Assistant go to **[Settings → Add-ons → Add-on store](https://my.home-assistant.io/redirect/supervisor_store/)** and install the **[Mosquitto broker](https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_mosquitto)** add-on, then start it.
-1. Go back to the **Add-on store**, click **⋮ → Repositories**, fill in `https://github.com/zigbee2mqtt/hassio-zigbee2mqtt` and click **Add → Close** or click the **Add repository** button below, click **Add → Close** (You might need to enter the **internal IP address** of your Home Assistant instance first).
- [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fzigbee2mqtt%2Fhassio-zigbee2mqtt)
-1. The repository includes two add-ons:
+The repository includes two add-ons:
- **Zigbee2MQTT** is the stable release that tracks the released versions of Zigbee2MQTT. (**recommended for most users**)
- **Zigbee2MQTT Edge** tracks the `dev` branch of Zigbee2MQTT such that you can install the edge version if there are features or fixes in the Zigbee2MQTT dev branch that are not yet released.
-1. Click on the add-on and press **Install** and wait till the add-on is installed.
+
+[](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fzigbee2mqtt%2Fhassio-zigbee2mqtt)
+
+For more details: https://www.home-assistant.io/common-tasks/os#installing-a-third-party-add-on-repository
+
+## Installation
+
+1. If you don't have an MQTT broker yet; in Home Assistant go to **[Settings → Add-ons → Add-on store](https://my.home-assistant.io/redirect/supervisor_store/)** and install the **[Mosquitto broker](https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_mosquitto)** add-on, then start it.
+1. Click on the desired Zigbee2MQTT add-on in **[Settings → Add-ons → Add-on store](https://my.home-assistant.io/redirect/supervisor_store/)** and press **Install**. Wait until the add-on is installed.
1. Start the add-on by going to **Info** and click **Start**
1. Wait a few seconds and press **OPEN WEB UI**, you will now see the onboarding page. More information about the onboarding can be found [here](https://www.zigbee2mqtt.io/guide/getting-started/#onboarding).
1. Fill in the desired settings, for most setups changing the following is enough:
diff --git a/common/Dockerfile b/common/Dockerfile
deleted file mode 100644
index 20201ef85..000000000
--- a/common/Dockerfile
+++ /dev/null
@@ -1,57 +0,0 @@
-ARG BUILD_FROM
-FROM $BUILD_FROM as base
-
-ENV LANG C.UTF-8
-ARG BUILD_VERSION
-
-RUN apk add --no-cache socat tini nodejs eudev && \
- # Validation to confirm that curl is installed in the base image.
- curl --version || (echo "curl missing" && exit 1)
-
-# Dependencies and build
-FROM base as dependencies_and_build
-
-RUN apk add --no-cache --virtual .buildtools npm make gcc g++ linux-headers udev git python3 && \
- if [ "${BUILD_VERSION}" = "edge" ]; \
- then \
- echo "Installing Edge version" && \
- git clone -b dev --single-branch --depth 1 \
- https://github.com/Koenkk/zigbee2mqtt.git /app && \
- mkdir /app/dist && \
- jq -n --arg commit $(eval cd /app;git rev-parse --short HEAD) '$commit' > /app/dist/.hash ; \
- else \
- echo "Installing Stable version ${BUILD_VERSION%-*}" && \
- curl -sL -o "/app.tar.gz" \
- "https://github.com/Koenkk/zigbee2mqtt/archive/${BUILD_VERSION%-*}.tar.gz" && \
- tar xzvf "/app.tar.gz" && rm "/app.tar.gz" && \
- mv -v "zigbee2mqtt-${BUILD_VERSION%-*}" app && \
- mkdir /app/dist && \
- jq -n --arg commit ${BUILD_VERSION%-*} '$commit' > /app/dist/.hash ; \
- fi; \
- echo "Installed Zigbee2MQTT @ version $(cat /app/dist/.hash)" && \
- cd /app && \
- npm install -g $(jq -r '.packageManager' package.json) && \
- pnpm install --frozen-lockfile --no-optional --unsafe-perm && \
- pnpm run build && \
- rm -rf node_modules && \
- pnpm install --frozen-lockfile --no-optional --unsafe-perm --prod && \
- # force serialport to rebuild on current platform instead of using prebuilds
- rm -rf `find ./node_modules/.pnpm/ -wholename "*/@serialport/bindings-cpp/prebuilds" -type d` && \
- pnpm rebuild @serialport/bindings-cpp
-
-# Release
-FROM base as release
-
-WORKDIR /app
-
-COPY rootfs /
-COPY --from=dependencies_and_build /app/node_modules ./node_modules
-COPY --from=dependencies_and_build /app/dist ./dist
-COPY --from=dependencies_and_build /app/package.json /app/LICENSE /app/index.js ./
-
-ENV NODE_ENV production
-
-HEALTHCHECK --interval=1m --timeout=3s --start-period=30s --start-interval=3s \
- CMD curl -f http://localhost:8099/
-
-ENTRYPOINT [ "/sbin/tini", "--", "/docker-entrypoint.sh"]
diff --git a/common/build.yaml b/common/build.yaml
deleted file mode 100644
index 5fe5b1004..000000000
--- a/common/build.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.22
- amd64: ghcr.io/home-assistant/amd64-base:3.22
diff --git a/common/local_build.sh b/common/local_build.sh
deleted file mode 100755
index 85b58c4f4..000000000
--- a/common/local_build.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-cd ..
-cp common/Dockerfile zigbee2mqtt-edge/
-cp -R common/rootfs zigbee2mqtt-edge/
-docker run --rm --privileged \
--v $(pwd)/zigbee2mqtt-edge:/data homeassistant/amd64-builder --amd64 -t /data \
---no-cache
-rm -rf zigbee2mqtt-edge/rootfs
-rm zigbee2mqtt-edge/Dockerfile
\ No newline at end of file
diff --git a/common/rootfs/docker-entrypoint.sh b/common/rootfs/docker-entrypoint.sh
deleted file mode 100755
index ea36c31e1..000000000
--- a/common/rootfs/docker-entrypoint.sh
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env bashio
-
-bashio::log.info "Preparing to start..."
-
-# Check if HA supervisor started
-# Workaround for:
-# - https://github.com/home-assistant/supervisor/issues/3884
-# - https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/issues/387
-bashio::config.require 'data_path'
-
-# Socat
-if bashio::config.true 'socat.enabled'; then
- bashio::log.info "Socat enabled"
- SOCAT_MASTER=$(bashio::config 'socat.master')
- SOCAT_SLAVE=$(bashio::config 'socat.slave')
-
- # Validate input
- if [[ -z "$SOCAT_MASTER" ]]; then
- bashio::exit.nok "Socat is enabled but not started because no master address specified"
- fi
- if [[ -z "$SOCAT_SLAVE" ]]; then
- bashio::exit.nok "Socat is enabled but not started because no slave address specified"
- fi
- bashio::log.info "Starting socat"
-
- DATA_PATH=$(bashio::config 'data_path')
- SOCAT_OPTIONS=$(bashio::config 'socat.options')
-
- # Socat start configuration
- bashio::log.blue "Socat startup parameters:"
- bashio::log.blue "Options: $SOCAT_OPTIONS"
- bashio::log.blue "Master: $SOCAT_MASTER"
- bashio::log.blue "Slave: $SOCAT_SLAVE"
-
- bashio::log.info "Starting socat process ..."
- exec socat $SOCAT_OPTIONS $SOCAT_MASTER $SOCAT_SLAVE &
-
- bashio::log.debug "Modifying process for logging if required"
- if bashio::config.true 'socat.log'; then
- bashio::log.debug "Socat loggin enabled, setting file path to $DATA_PATH/socat.log"
- exec &>"$DATA_PATH/socat.log" 2>&1
- else
- bashio::log.debug "No logging required"
- fi
-else
- bashio::log.info "Socat not enabled"
-fi
-
-export ZIGBEE2MQTT_DATA="$(bashio::config 'data_path')"
-mkdir -p "$ZIGBEE2MQTT_DATA" || bashio::exit.nok "Could not create $ZIGBEE2MQTT_DATA"
-
-if bashio::config.has_value 'watchdog'; then
- export Z2M_WATCHDOG="$(bashio::config 'watchdog')"
- bashio::log.info "Enabled Zigbee2MQTT watchdog with value '$Z2M_WATCHDOG'"
-fi
-
-export NODE_PATH=/app/node_modules
-export ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED='true'
-export ZIGBEE2MQTT_CONFIG_FRONTEND_PORT='8099'
-export ZIGBEE2MQTT_CONFIG_HOMEASSISTANT_ENABLED='true'
-export Z2M_ONBOARD_URL='http://0.0.0.0:8099'
-
-if bashio::config.true 'force_onboarding'; then
- export Z2M_ONBOARD_FORCE_RUN="1"
- bashio::log.info "Forcing onboard to run"
-fi
-
-if bashio::config.true 'disable_tuya_default_response'; then
- bashio::log.info "Disabling TuYa default responses"
- export DISABLE_TUYA_DEFAULT_RESPONSE="true"
-fi
-
-# Expose addon configuration through environment variables.
-function export_config() {
- local key=${1}
- local subkey
-
- if bashio::config.is_empty "${key}"; then
- return
- fi
-
- for subkey in $(bashio::jq "$(bashio::config "${key}")" 'keys[]'); do
- export "ZIGBEE2MQTT_CONFIG_$(bashio::string.upper "${key}")_$(bashio::string.upper "${subkey}")=$(bashio::config "${key}.${subkey}")"
- done
-}
-
-export_config 'mqtt'
-export_config 'serial'
-
-export TZ="$(bashio::supervisor.timezone)"
-
-if (bashio::config.is_empty 'mqtt' || ! (bashio::config.has_value 'mqtt.server' || bashio::config.has_value 'mqtt.user' || bashio::config.has_value 'mqtt.password')) && bashio::var.has_value "$(bashio::services 'mqtt')"; then
- if bashio::var.true "$(bashio::services 'mqtt' 'ssl')"; then
- export ZIGBEE2MQTT_CONFIG_MQTT_SERVER="mqtts://$(bashio::services 'mqtt' 'host'):$(bashio::services 'mqtt' 'port')"
- else
- export ZIGBEE2MQTT_CONFIG_MQTT_SERVER="mqtt://$(bashio::services 'mqtt' 'host'):$(bashio::services 'mqtt' 'port')"
- fi
- export ZIGBEE2MQTT_CONFIG_MQTT_USER="$(bashio::services 'mqtt' 'username')"
- export ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD="$(bashio::services 'mqtt' 'password')"
-fi
-
-bashio::log.info "Starting Zigbee2MQTT..."
-cd /app
-exec node index.js
diff --git a/zigbee2mqtt/CHANGELOG.md b/zigbee2mqtt/CHANGELOG.md
index 44620834a..85fef6c31 100644
--- a/zigbee2mqtt/CHANGELOG.md
+++ b/zigbee2mqtt/CHANGELOG.md
@@ -1,3 +1,14 @@
+
+
+## 2.8.0
+
+- [Zigbee2MQTT release notes](https://github.com/Koenkk/zigbee2mqtt/releases/tag/2.8.0)
+- **ADD-ON BREAKING CHANGES**
+- Remove add-on configs that are available through onboarding
+- Improve add-on configs with labels
+- Migrate to new add-on builder
+- Migrate to addon_config
+
## 2.6.3-1
- Updated Zigbee2MQTT to version [`2.6.3`](https://github.com/Koenkk/zigbee2mqtt/releases/tag/2.6.3)
diff --git a/zigbee2mqtt/DOCS.md b/zigbee2mqtt/DOCS.md
index 6121bd6ad..a3bcce687 100644
--- a/zigbee2mqtt/DOCS.md
+++ b/zigbee2mqtt/DOCS.md
@@ -1,88 +1,12 @@
-# Pairing
+# Home Assistant Add-on: Zigbee2MQTT
-By default the add-on has `permit_join` set to `false`. To allow devices to join you need to activate this after the add-on has started. You can now use the [built-in frontend](https://www.zigbee2mqtt.io/information/frontend.html) to achieve this. For details on how to enable the built-in frontent see the next section.
-
-# Enabling the built-in frontend
-
-Enable `ingress` to have the frontend available in your UI: **Settings → Add-ons → Zigbee2MQTT → Show in sidebar**. You can find more details about the feature on the [Zigbee2MQTT documentation](https://www.zigbee2mqtt.io/information/frontend.html).
-
-# Configuration
-
-## Onboarding
+## How to use
[Onboarding](https://www.zigbee2mqtt.io/guide/getting-started/#onboarding) allows you to setup Zigbee2MQTT without having to manually enter the details in the add-on configuration page. When starting the add-on with a brand new install (no configuration present), the frontend will show a quick setup page, allowing you to select various settings for Zigbee2MQTT to be able to start.
> [!NOTE]
> Successful detection of adapters, to select from, may vary based on your setup/network. You may have to enter these [details manually](https://www.zigbee2mqtt.io/guide/configuration/adapter-settings.html#basic-configuration) on the page instead.
-> [!TIP]
-> You can force the onboarding to re-run (e.g. changing adapter) using the toggle available in the add-on configuration page (visible after checking `Show unused optional configuration options`). This will force onboarding to run even after you have successfully configured it for the first time. Make sure to disable it once done.
-
-## Manual
-
-Configuration required to startup Zigbee2MQTT is available from the add-on configuration. The rest of the options can be configured via the Zigbee2MQTT frontend.
-
-> [!CAUTION]
-> Settings configured through the add-on configuration page will take precedence over settings in the `configuration.yaml` page (e.g. you set `rtscts: false` in add-on configuration page and `rtscts: true` in `configuration.yaml`, `rtscts: false` will be used). _If you want to control the entire configuration through YAML, remove them from the add-on configuration page._
-
-#### Examples for each configuration section
-
-- socat
- ```yaml
- enabled: false
- master: pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777
- slave: tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5
- options: "-d -d"
- log: false
- ```
-- mqtt
- ```yaml
- server: mqtt://localhost:1883
- user: my_user
- password: "my_password"
- ```
-- serial
- ```yaml
- adapter: zstack
- port: /dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B0018ED3DDF-if00
- ```
-
-# Configuration backup
-
-The add-on will create a backup of your configuration.yml within your data path: `$DATA_PATH/configuration.yaml.bk`. When upgrading, you should use this to fill in the relevant values into your new config, particularly the network key, to avoid breaking your network and having to re-pair all of your devices.
-The backup of your configuration is created on add-on startup if no previous backup was found.
-
-# Enabling the watchdog
-
-To automatically restart Zigbee2MQTT in case of a soft failure (like "adapter disconnected"), the watchdog can be used. It can be enabled by adding the following to the add-on configuration:
-
-```yaml
-watchdog: default
-```
-
-This will use the default watchdog retry delays of 1min, 5min, 15min, 30min, 60min. Custom delays are also supported, e.g. `watchdog: 5,10,30` will start Zigbee2MQTT with the watchdog's retry delays of 5min, 10min, 30min. For more information about the watchdog, read the [docs](https://www.zigbee2mqtt.io/guide/installation/15_watchdog.html).
-
# Adding Support for New Devices
If you are interested in adding support for new devices to Zigbee2MQTT see [How to support new devices](https://www.zigbee2mqtt.io/how_tos/how_to_support_new_devices.html).
-
-# Notes
-
-- Depending on your configuration, the MQTT server config may need to include the port, typically `1883` or `8883` for SSL communications. For example, `mqtt://core-mosquitto:1883` for Home Assistant's Mosquitto add-on.
-- To find out which serial ports you have exposed go to **Supervisor → System → Host system → ⋮ → Hardware**
-
-# Socat
-
-In some cases it is not possible to forward a serial device to the container that zigbee2mqtt runs in. This could be because the device is not physically connected to the machine at all.
-
-Socat can be used to forward a serial device over TCP to zigbee2mqtt. See the [socat man pages](https://linux.die.net/man/1/socat) for more info.
-
-You can configure the socat module within the socat section using the following options:
-
-- `enabled` true/false to enable socat (default: false)
-- `master` master or first address used in socat command line (mandatory)
-- `slave` slave or second address used in socat command line (mandatory)
-- `options` extra options added to the socat command line (optional)
-- `log` true/false if to log the socat stdout/stderr to data_path/socat.log (default: false)
-
-**NOTE:** You'll have to change both the `master` and the `slave` options according to your needs. The defaults values will make sure that socat listens on port `8485` and redirects its output to `/dev/ttyZ2M`. The zigbee2mqtt's serial port setting is NOT automatically set and has to be changed accordingly.
diff --git a/zigbee2mqtt/Dockerfile b/zigbee2mqtt/Dockerfile
new file mode 100644
index 000000000..c6570ec00
--- /dev/null
+++ b/zigbee2mqtt/Dockerfile
@@ -0,0 +1,38 @@
+# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile
+ARG BUILD_FROM
+FROM $BUILD_FROM AS base
+
+ENV LANG=C.UTF-8
+
+RUN apk --no-cache add socat tini nodejs eudev tzdata
+
+FROM base AS deps_and_build
+
+ARG ZIGBEE2MQTT_VERSION
+RUN \
+ apk add --no-cache --virtual .buildtools npm make gcc g++ linux-headers udev git python3 \
+ && mkdir -p /app/dist \
+ && curl -sSLf -o "/app.tar.gz" "https://github.com/Koenkk/zigbee2mqtt/archive/${ZIGBEE2MQTT_VERSION}.tar.gz" \
+ && tar -C /app --strip-components=1 -xzvf "/app.tar.gz" \
+ && rm -rf "/app.tar.gz" \
+ && echo ${ZIGBEE2MQTT_VERSION} > /app/dist/.hash \
+ && cd /app \
+ && npm i -g $(jq -r '.packageManager' package.json) \
+ && pnpm i --frozen-lockfile --no-optional \
+ && pnpm run build \
+ && rm -rf node_modules \
+ && pnpm i --frozen-lockfile --no-optional --prod \
+ # force serialport to rebuild on current platform instead of using prebuilds
+ && rm -rf `find ./node_modules/.pnpm/ -wholename "*/@serialport/bindings-cpp/prebuilds" -type d` \
+ && pnpm rebuild @serialport/bindings-cpp
+
+FROM base AS release
+
+COPY rootfs /
+
+WORKDIR /app
+ENV NODE_ENV=production
+
+COPY --from=deps_and_build /app/node_modules ./node_modules
+COPY --from=deps_and_build /app/dist ./dist
+COPY --from=deps_and_build /app/package.json /app/LICENSE /app/index.js ./
diff --git a/zigbee2mqtt/README.md b/zigbee2mqtt/README.md
index eecbde234..c54908dcf 100644
--- a/zigbee2mqtt/README.md
+++ b/zigbee2mqtt/README.md
@@ -1,6 +1,9 @@
# Home Assistant Add-on: Zigbee2MQTT
-[](https://cloud.docker.com/u/dwelch2101/repository/docker/zigbee2mqtt/zigbee2mqtt-amd64)
+
+[](https://cloud.docker.com/u/dwelch2101/repository/docker/zigbee2mqtt/zigbee2mqtt-aarch64)
+
+[](https://cloud.docker.com/u/dwelch2101/repository/docker/zigbee2mqtt/zigbee2mqtt-amd64)
Allows you to use your Zigbee devices **without** the vendors bridge or gateway.
diff --git a/zigbee2mqtt/build.yaml b/zigbee2mqtt/build.yaml
new file mode 100644
index 000000000..dd819a0d6
--- /dev/null
+++ b/zigbee2mqtt/build.yaml
@@ -0,0 +1,11 @@
+# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile
+build_from:
+ aarch64: "ghcr.io/home-assistant/aarch64-base:3.22"
+ amd64: "ghcr.io/home-assistant/amd64-base:3.22"
+labels:
+ org.opencontainers.image.title: "Home Assistant Add-on: Zigbee2MQTT"
+ org.opencontainers.image.description: "Use your ZigBee devices without the vendor's bridge or gateway"
+ org.opencontainers.image.source: "https://github.com/zigbee2mqtt/hassio-zigbee2mqtt"
+ org.opencontainers.image.licenses: "Apache License 2.0"
+args:
+ ZIGBEE2MQTT_VERSION: "2.8.0"
diff --git a/zigbee2mqtt/config.json b/zigbee2mqtt/config.json
deleted file mode 100644
index 363f2f57b..000000000
--- a/zigbee2mqtt/config.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
- "name": "Zigbee2MQTT",
- "version": "2.6.3-1",
- "slug": "zigbee2mqtt",
- "description": "Use your ZigBee devices without the vendor's bridge or gateway",
- "breaking_versions": [
- "2.0.0-1"
- ],
- "uart": true,
- "udev": true,
- "url": "https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/tree/master/zigbee2mqtt",
- "startup": "application",
- "services": [
- "mqtt:need"
- ],
- "hassio_api": true,
- "arch": [
- "aarch64",
- "amd64"
- ],
- "boot": "auto",
- "init": false,
- "ingress": true,
- "timeout": 30,
- "panel_icon": "mdi:zigbee",
- "map": [
- {
- "type": "share",
- "read_only": false
- },
- {
- "type": "homeassistant_config",
- "read_only": false,
- "path": "/config"
- },
- {
- "type": "addon_config",
- "read_only": false,
- "path": "/addon_config"
- }
- ],
- "ports": {
- "8485/tcp": 8485,
- "8099/tcp": null
- },
- "ports_description": {
- "8485/tcp": "Socat tcp-listen port",
- "8099/tcp": "Frontend tcp-listen port"
- },
- "options": {
- "data_path": "/config/zigbee2mqtt",
- "socat": {
- "enabled": false,
- "master": "pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777",
- "slave": "tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5",
- "options": "-d -d",
- "log": false
- },
- "mqtt": {},
- "serial": {}
- },
- "schema": {
- "data_path": "str",
- "socat": {
- "enabled": "bool?",
- "master": "str?",
- "slave": "str?",
- "options": "str?",
- "log": "bool?"
- },
- "mqtt": {
- "server": "str?",
- "ca": "str?",
- "key": "str?",
- "cert": "str?",
- "user": "str?",
- "password": "str?",
- "base_topic": "str?"
- },
- "serial": {
- "port": "str?",
- "adapter": "match(zstack|deconz|zigate|ezsp|ember|zboss)?",
- "baudrate": "int?",
- "rtscts": "bool?"
- },
- "watchdog": "str?",
- "force_onboarding": "bool?"
- },
- "image": "ghcr.io/zigbee2mqtt/zigbee2mqtt-{arch}"
-}
\ No newline at end of file
diff --git a/zigbee2mqtt/config.yaml b/zigbee2mqtt/config.yaml
new file mode 100644
index 000000000..31205aa27
--- /dev/null
+++ b/zigbee2mqtt/config.yaml
@@ -0,0 +1,49 @@
+# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
+name: Zigbee2MQTT
+version: "2.8.0"
+breaking_versions: ["2.8.0"]
+slug: zigbee2mqtt
+description: Use your ZigBee devices without the vendor's bridge or gateway
+url: "https://github.com/zigbee2mqtt/hassio-zigbee2mqtt/tree/master/zigbee2mqtt"
+panel_icon: "mdi:zigbee"
+arch:
+ - aarch64
+ - amd64
+image: "ghcr.io/zigbee2mqtt/zigbee2mqtt-{arch}"
+init: false
+ingress: true
+uart: true
+udev: true
+hassio_api: true
+timeout: 30
+services:
+ - mqtt:need
+map:
+ # @deprecated for migration purpose only
+ - type: homeassistant_config
+ read_only: false
+ path: /config
+ - type: addon_config
+ read_only: false
+ path: /addon_config
+ports:
+ "8099/tcp": null
+ "8485/tcp": 8485
+options:
+ watchdog: default
+ force_onboarding: false
+ socat_enabled: false
+ socat_master: "pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777"
+ socat_slave: "tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5"
+ socat_options: "-d -d"
+ socat_log: false
+schema:
+ # @deprecated for migration purpose only
+ data_path: "str?"
+ watchdog: "str?"
+ force_onboarding: bool
+ socat_enabled: "bool?"
+ socat_master: "str?"
+ socat_slave: "str?"
+ socat_options: "str?"
+ socat_log: "bool?"
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt
new file mode 100644
index 000000000..e69de29bb
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt-migrate-config b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbee2mqtt-migrate-config
new file mode 100644
index 000000000..e69de29bb
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/dependencies.d/base b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/dependencies.d/base
new file mode 100644
index 000000000..e69de29bb
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/type b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/type
new file mode 100644
index 000000000..3d92b15f2
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/type
@@ -0,0 +1 @@
+oneshot
\ No newline at end of file
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/up b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/up
new file mode 100644
index 000000000..30335a8e8
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt-migrate-config/up
@@ -0,0 +1 @@
+/etc/s6-overlay/scripts/zigbee2mqtt-migrate-config.sh
\ No newline at end of file
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/dependencies.d/zigbee2mqtt-migrate-config b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/dependencies.d/zigbee2mqtt-migrate-config
new file mode 100644
index 000000000..e69de29bb
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/finish b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/finish
new file mode 100644
index 000000000..fd8ef0ba5
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/finish
@@ -0,0 +1,28 @@
+#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# Take down the S6 supervision tree when daemon fails
+# ==============================================================================
+# shellcheck disable=SC2155
+
+readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ fi
+ [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt
+elif [[ "${exit_code_service}" -ne 0 ]]; then
+ if [[ "${exit_code_container}" -eq 0 ]]; then
+ echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode
+ fi
+ exec /run/s6/basedir/bin/halt
+fi
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/run b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/run
new file mode 100644
index 000000000..047aaa7ec
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/run
@@ -0,0 +1,93 @@
+#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Start the nginx service
+# s6-overlay docs: https://github.com/just-containers/s6-overlay
+# ==============================================================================
+# shellcheck disable=SC2155
+
+set -e
+
+bashio::log.info "Configuring Zigbee2MQTT..."
+
+export ZIGBEE2MQTT_DATA="/addon_config"
+
+mkdir -p "$ZIGBEE2MQTT_DATA" || bashio::exit.nok "Could not create $ZIGBEE2MQTT_DATA"
+
+if bashio::var.has_value "$(bashio::services 'mqtt')"; then
+ if bashio::var.true "$(bashio::services 'mqtt' 'ssl')"; then
+ export ZIGBEE2MQTT_CONFIG_MQTT_SERVER="mqtts://$(bashio::services 'mqtt' 'host'):$(bashio::services 'mqtt' 'port')"
+ else
+ export ZIGBEE2MQTT_CONFIG_MQTT_SERVER="mqtt://$(bashio::services 'mqtt' 'host'):$(bashio::services 'mqtt' 'port')"
+ fi
+ export ZIGBEE2MQTT_CONFIG_MQTT_USER="$(bashio::services 'mqtt' 'username')"
+ export ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD="$(bashio::services 'mqtt' 'password')"
+else
+ bashio::log.warning "MQTT service configuration unavailable"
+fi
+
+# Socat
+if bashio::config.true 'socat_enabled'; then
+ bashio::log.info "Socat enabled"
+ SOCAT_MASTER=$(bashio::config 'socat_master')
+ SOCAT_SLAVE=$(bashio::config 'socat_slave')
+
+ # Validate input
+ if bashio::var.is_empty "$SOCAT_MASTER"; then
+ bashio::exit.nok "Socat is enabled but not started because no master address specified"
+ fi
+
+ if bashio::var.is_empty "$SOCAT_SLAVE"; then
+ bashio::exit.nok "Socat is enabled but not started because no slave address specified"
+ fi
+
+ bashio::log.info "Starting socat"
+
+ SOCAT_OPTIONS=$(bashio::config 'socat_options')
+
+ # Socat start configuration
+ bashio::log.blue "Socat startup parameters:"
+ bashio::log.blue "Options: $SOCAT_OPTIONS"
+ bashio::log.blue "Master: $SOCAT_MASTER"
+ bashio::log.blue "Slave: $SOCAT_SLAVE"
+
+ bashio::log.info "Starting socat process ..."
+ exec socat "$SOCAT_OPTIONS" "$SOCAT_MASTER" "$SOCAT_SLAVE" &
+
+ bashio::log.debug "Modifying process for logging if required"
+
+ if bashio::config.true 'socat_log'; then
+ bashio::log.debug "Socat loggin enabled, setting file path to $ZIGBEE2MQTT_DATA/socat.log"
+ exec &>"$ZIGBEE2MQTT_DATA/socat.log" 2>&1
+ else
+ bashio::log.debug "No logging required"
+ fi
+else
+ bashio::log.info "Socat not enabled"
+fi
+
+if bashio::config.has_value 'watchdog'; then
+ export Z2M_WATCHDOG="$(bashio::config 'watchdog')"
+ bashio::log.info "Enabled Zigbee2MQTT watchdog with value '$Z2M_WATCHDOG'"
+fi
+
+if bashio::config.true 'force_onboarding'; then
+ export Z2M_ONBOARD_FORCE_RUN="1"
+ bashio::log.info "Forcing onboarding to run"
+fi
+
+export TZ="$(bashio::supervisor.timezone)"
+export ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED='true'
+export ZIGBEE2MQTT_CONFIG_FRONTEND_PORT='8099'
+export ZIGBEE2MQTT_CONFIG_HOMEASSISTANT_ENABLED='true'
+export Z2M_ONBOARD_URL='http://0.0.0.0:8099'
+
+cd /app
+
+if [ -d "$ZIGBEE2MQTT_DATA/app_overrides" ]; then
+ bashio::log.info "Applying app overrides..."
+ cp -R "$ZIGBEE2MQTT_DATA/app_overrides/." ./ || bashio::exit.nok "Could not apply app overrides"
+fi
+
+bashio::log.info "Starting Zigbee2MQTT..."
+exec node index.js
\ No newline at end of file
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/type b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/type
new file mode 100644
index 000000000..1780f9f44
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/s6-rc.d/zigbee2mqtt/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/zigbee2mqtt/rootfs/etc/s6-overlay/scripts/zigbee2mqtt-migrate-config.sh b/zigbee2mqtt/rootfs/etc/s6-overlay/scripts/zigbee2mqtt-migrate-config.sh
new file mode 100644
index 000000000..d8adcf9c1
--- /dev/null
+++ b/zigbee2mqtt/rootfs/etc/s6-overlay/scripts/zigbee2mqtt-migrate-config.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Start the nginx service
+# s6-overlay docs: https://github.com/just-containers/s6-overlay
+# ==============================================================================
+# shellcheck disable=SC2155
+
+set -e
+
+z2m_config="$(bashio::config 'data_path')"
+
+if bashio::var.is_empty "$z2m_config"; then
+ bashio::log.info "data_path is unspecified. No migration necessary."
+
+ bashio::exit.ok
+fi
+
+if bashio::var.equals "$z2m_config" "/addon_config" || bashio::var.equals "$z2m_config" "/addon_config/";then
+ bashio::log.info "data_path is already '/addon_config'. No migration necessary."
+
+ bashio::exit.ok
+fi
+
+if ! bashio::fs.directory_exists "$z2m_config"; then
+ bashio::log.info "data_path '$z2m_config' does not exist. No migration necessary."
+
+ bashio::exit.ok
+fi
+
+if [[ "$(ls -A "$z2m_config" | wc -l)" -eq 0 ]]; then
+ bashio::log.info "data_path '$z2m_config' is empty. No migration necessary."
+
+ rm -rfv "$z2m_config"
+ bashio::exit.ok
+fi
+
+function archive_src() {
+ tar -czvf "/addon_config/src-archive.tar.gz" "$z2m_config"
+ rm -rfv "$z2m_config"
+ bashio::log.info "Done archiving src."
+}
+
+bashio::log.info "Starting Zigbee2MQTT config migration..."
+
+# don't want the symlinks if they exist, Z2M will re-create as needed so can safely delete them
+rm -fv "$z2m_config/external_converters/node_modules" "$z2m_config/external_extensions/node_modules"
+rm -fv "/addon_config/external_converters/node_modules" "/addon_config/external_extensions/node_modules"
+
+if [[ $z2m_config == /addon_config/* ]]; then
+ bashio::log.info "data_path is nested under addon_config folder. Skipping dst archiving..."
+else
+ if [[ "$(ls -A "/addon_config" | wc -l)" -ne 0 ]]; then
+ bashio::log.info "New addon_config folder is not empty, archiving it..."
+
+ # if certain files exists in addon_config, check mtime
+ # check db first since it is always written on shutdown
+ if bashio::fs.file_exists "/addon_config/database.db"; then
+ if [[ "/addon_config/database.db" -nt "$z2m_config/database.db" ]]; then
+ bashio::log.info "/addon_config/database.db is newer. Skipping migration, only archiving src..."
+
+ archive_src
+ bashio::exit.ok
+ fi
+ else
+ # in case add-on onboarding was started but never finished, database.db does not exist
+ if bashio::fs.file_exists "/addon_config/configuration.yaml" \
+ && [[ "/addon_config/configuration.yaml" -nt "$z2m_config/configuration.yaml" ]]
+ then
+ bashio::log.info "/addon_config/configuration.yaml is newer. Skipping migration, only archiving src..."
+
+ archive_src
+ bashio::exit.ok
+ fi
+ fi
+
+ tar -czvf "/addon_config.dst-archive.tar.gz" "/addon_config"
+
+ # do not use `rm -rfv /addon_config/*` to remove content as that forces prompt with zsh
+ for item in /addon_config/*; do
+ rm -rfv "$item"
+ done
+
+ mv "/addon_config.dst-archive.tar.gz" "/addon_config/dst-archive.tar.gz"
+ bashio::log.info "Done archiving dst."
+ fi
+fi
+
+cp -R -d "$z2m_config/." "/addon_config"
+bashio::log.info "Done copying src to dst."
+
+archive_src
+
+bashio::log.info "Successfully migrated to addon_config."
diff --git a/zigbee2mqtt/translations/en.yaml b/zigbee2mqtt/translations/en.yaml
new file mode 100644
index 000000000..851592ce1
--- /dev/null
+++ b/zigbee2mqtt/translations/en.yaml
@@ -0,0 +1,44 @@
+---
+configuration:
+ # @deprecated for migration purpose only
+ data_path:
+ name: Data path (deprecated)
+ description: Used to migrate from previous version's folder to new backup-supporting addon_config folder, after which, this is no longer needed.
+ watchdog:
+ name: Watchdog
+ description: >-
+ Automatically restart Zigbee2MQTT in case of a soft failure (like 'adapter disconnected').
+ Using `default` will use the retry delays 1min, 5min, 15min, 30min, 60min.
+ Custom delays are also supported, e.g. `5,10,30` will start Zigbee2MQTT with the watchdog's retry delays set to 5min, 10min, 30min.
+ https://www.zigbee2mqtt.io/guide/installation/15_watchdog.html
+ force_onboarding:
+ name: Force onboarding
+ description: >-
+ Force the onboarding to run even if it was previously done.
+ Can be used for e.g. when changing adapter to update the serial port.
+ Make sure to disable once done.
+ socat_enabled:
+ name: Enable Socat
+ description: >-
+ Socat can be used to forward a serial device over TCP to Zigbee2MQTT.
+ The defaults values will make sure that socat listens on port `8485` and redirects its output to `/dev/ttyZ2M`.
+ https://linux.die.net/man/1/socat
+ socat_master:
+ name: Socat Master
+ description: >-
+ Master or first address used in socat command line (mandatory if socat enabled).
+ Example: `pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777`
+ socat_slave:
+ name: Socat Slave
+ description: >-
+ Slave or second address used in socat command line (mandatory if socat enabled).
+ Example: `tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5`
+ socat_options:
+ name: Socat Options
+ description: >-
+ Extra options added to the socat command line.
+ Example: `-d -d`
+ socat_log:
+ name: Socat Enable Logging
+ description: >-
+ Log the socat stdout/stderr to /config/socat.log