diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index b75098ee007..7b7e5524390 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,5 +1,5 @@
{
- "name": "Home Assistant Add-ons",
+ "name": "Home Assistant Apps",
"image": "ghcr.io/home-assistant/devcontainer:addons",
"appPort": ["7123:8123", "7357:4357"],
"postStartCommand": "bash devcontainer_bootstrap",
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 6a331190b3a..8670b505c81 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,16 +1,16 @@
---
# yamllint disable rule:line-length
name: Bug Report Form
-description: Report an issue related to one of the official add-ons.
+description: Report an issue related to one of the official apps (formerly known as add-ons).
body:
- type: markdown
attributes:
value: |
This issue form is for reporting bugs with **supported** setups only!
- If you have a feature or enhancement request, please use the [feature request][fr] section of our [Community Forum][fr].
+ If you have a feature or enhancement request, please use our [Feature Requests][fr].
- [fr]: https://community.home-assistant.io/c/feature-requests
+ [fr]: https://github.com/orgs/home-assistant/discussions
- type: textarea
validations:
@@ -50,12 +50,11 @@ body:
validations:
required: true
attributes:
- label: Which add-on are you reporting an issue with?
+ label: Which app are you reporting an issue with?
options:
- CEC Scanner
- File editor
- deCONZ
- - DHCP Server
- Dnsmasq
- Duck DNS
- Git pull
@@ -72,7 +71,6 @@ body:
- Silicon Labs Flasher
- Silicon Labs Multiprotocol
- Terminal & SSH
- - TellStick
- VLC
- Whisper
- Z-Wave JS
@@ -81,8 +79,8 @@ body:
validations:
required: true
attributes:
- label: What is the version of the add-on?
- description: Can be found in [Settings -> Add-ons](https://my.home-assistant.io/redirect/supervisor/) -> the add-on
+ label: What is the version of the app?
+ description: Can be found in [Settings > Apps](https://my.home-assistant.io/redirect/supervisor/) -> the app
- type: markdown
attributes:
@@ -126,10 +124,10 @@ body:
- type: textarea
attributes:
- label: Anything in the add-on logs that might be useful for us?
+ label: Anything in the app logs that might be useful for us?
description: >
- Addon Logs can be found in [Settings -> System -> Logs](https://my.home-assistant.io/redirect/logs/)
- then choose the add-on in the top right.
+ App Logs can be found in [Settings > System > Logs](https://my.home-assistant.io/redirect/logs/)
+ then choose the app in the top right.
[](https://my.home-assistant.io/redirect/logs/)
render: txt
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 9063623ce8c..dd64fe56f3d 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -7,7 +7,7 @@ contact_links:
about: This is the issue tracker for our backend. Please report issues with the UI in the frontend repository.
- name: Report a bug with Home Assistant
url: https://github.com/home-assistant/core/issues
- about: This is the issue tracker for our add-ons. Please report issues with the core software in the core repository.
+ about: This is the issue tracker for our apps (formerly known as add-ons). Please report issues with the core software in the core repository.
- name: Report incorrect or missing information on our website
url: https://github.com/home-assistant/home-assistant.io/issues
about: Our documentation has its own issue tracker. Please report issues with the website there.
@@ -15,8 +15,8 @@ contact_links:
url: https://www.home-assistant.io/help
about: We use GitHub for tracking bugs, check our website for resources on getting help.
- name: Feature Request
- url: https://community.home-assistant.io/c/feature-requests
- about: Please use our Community Forum for making feature requests.
+ url: https://github.com/orgs/home-assistant/discussions
+ about: Please use our GitHub Discussions for making feature requests.
- name: I'm unsure where to go
url: https://www.home-assistant.io/join-chat
about: If you are unsure where to go, then joining our chat is recommended; Just ask!
diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml
new file mode 100644
index 00000000000..62d1a3122d4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/task.yml
@@ -0,0 +1,63 @@
+---
+name: Task
+description: For staff only - Create a task
+type: Task
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ## ⚠️ RESTRICTED ACCESS
+
+ **This form is restricted to Open Home Foundation staff and
+ authorized contributors only.**
+
+ If you are a community member wanting to contribute, please:
+ - For bug reports: Use the
+ [bug report form](https://github.com/home-assistant/addons/issues/new
+ ?template=bug_report.yml)
+ - For feature requests: Submit to
+ [Feature Requests](https://github.com/orgs/home-assistant/discussions)
+
+ ---
+
+ ### For authorized contributors
+
+ Use this form to create tasks for development work, improvements,
+ or other actionable items that need to be tracked.
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: |
+ Provide a clear and detailed description of the task that needs
+ to be accomplished.
+
+ Be specific about what needs to be done, why it's important, and
+ any constraints or requirements.
+ placeholder: |
+ Describe the task, including:
+ - What needs to be done
+ - Why this task is needed
+ - Expected outcome
+ - Any constraints or requirements
+ validations:
+ required: true
+ - type: textarea
+ id: additional_context
+ attributes:
+ label: Additional context
+ description: |
+ Any additional information, links, research, or context that
+ would be helpful.
+
+ Include links to related issues, research, prototypes, roadmap
+ opportunities etc.
+ placeholder: |
+ - Roadmap opportunity: [link]
+ - Epic: [link]
+ - Feature request: [link]
+ - Technical design documents: [link]
+ - Prototype/mockup: [link]
+ - Dependencies: [links]
+ validations:
+ required: false
diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml
index fa5db235233..7ebfabded92 100644
--- a/.github/workflows/builder.yml
+++ b/.github/workflows/builder.yml
@@ -1,6 +1,6 @@
---
# yamllint disable rule:line-length rule:truthy
-name: Build add-on
+name: Build app
env:
BUILD_ARGS: "--test"
@@ -22,13 +22,13 @@ jobs:
changed: ${{ steps.changed_addons.outputs.changed }}
steps:
- name: Check out the repository
- uses: actions/checkout@v4.1.2
+ uses: actions/checkout@v6.0.2
- name: Get changed files
id: changed_files
uses: masesgroup/retrieve-changed-files@v3.0.0
- - name: Get add-ons
+ - name: Get apps
id: addons
run: |
declare -a addons
@@ -37,7 +37,7 @@ jobs:
done
echo "addons=${addons[@]}" >> "$GITHUB_OUTPUT"
- - name: Get changed add-ons
+ - name: Get changed apps
id: changed_addons
run: |
declare -a changed_addons
@@ -55,26 +55,30 @@ jobs:
changed=$(echo ${changed_addons[@]} | rev | cut -c 2- | rev)
if [[ -n ${changed} ]]; then
- echo "Changed add-ons: $changed";
+ echo "Changed apps: $changed";
echo "changed=true" >> "$GITHUB_OUTPUT";
echo "addons=[$changed]" >> "$GITHUB_OUTPUT";
else
- echo "No add-on had any monitored files changed (${{ env.MONITORED_FILES }})";
+ echo "No app had any monitored files changed (${{ env.MONITORED_FILES }})";
fi
build:
needs: init
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.runs-on }}
if: needs.init.outputs.changed == 'true'
- name: Build ${{ matrix.arch }} ${{ matrix.addon }} add-on
+ name: Build ${{ matrix.arch }} ${{ matrix.addon }} app
strategy:
matrix:
addon: ${{ fromJson(needs.init.outputs.changed_addons) }}
- arch: ["aarch64", "amd64", "armhf", "armv7", "i386"]
+ arch: ["aarch64", "amd64"]
+ include:
+ - runs-on: ubuntu-24.04
+ - runs-on: ubuntu-24.04-arm
+ arch: aarch64
steps:
- name: Check out repository
- uses: actions/checkout@v4.1.2
+ uses: actions/checkout@v6.0.2
- name: Get information
id: info
@@ -82,7 +86,7 @@ jobs:
with:
path: "./${{ matrix.addon }}"
- - name: Check add-on
+ - name: Check app
id: check
run: |
if [[ "${{ steps.info.outputs.architectures }}" =~ ${{ matrix.arch }} ]]; then
@@ -100,15 +104,16 @@ jobs:
- name: Login to DockerHub
if: env.BUILD_ARGS == '--docker-hub-check'
- uses: docker/login-action@v3.1.0
+ uses: docker/login-action@v3.7.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Build ${{ matrix.addon }} add-on
+ - name: Build ${{ matrix.addon }} app
if: steps.check.outputs.build_arch == 'true'
- uses: home-assistant/builder@2024.03.5
+ uses: home-assistant/builder@2025.11.0
with:
+ image: ${{ matrix.arch }}
args: |
${{ env.BUILD_ARGS }} \
--${{ matrix.arch }} \
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index bd3de93cdeb..19ff23571d7 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -18,7 +18,7 @@ jobs:
name: hadolint
steps:
- name: Check out the repository
- uses: actions/checkout@v4.1.2
+ uses: actions/checkout@v6.0.2
- name: Run linter
id: changed_files
@@ -36,7 +36,7 @@ jobs:
name: YAMLLint
steps:
- name: Check out the repository
- uses: actions/checkout@v4.1.2
+ uses: actions/checkout@v6.0.2
- name: Run YAMLLint
uses: frenck/action-yamllint@v1.5
@@ -46,7 +46,23 @@ jobs:
name: ShellCheck
steps:
- name: Check out the repository
- uses: actions/checkout@v4.1.2
+ uses: actions/checkout@v6.0.2
- name: Run linter
uses: ludeeus/action-shellcheck@2.0.0
+ with:
+ # Names of scripts with custom shebangs that the action would not
+ # discover on its own:
+ additional_files: >-
+ check_certificate_renewal
+ cpcd-config-up
+ discovery
+ finish
+ lock-tables-for-backup
+ matter-server-discovery
+ reboot
+ run
+ shutdown
+ universal-silabs-flasher-up
+ unlock-tables-for-backup
+ vlc-discovery
diff --git a/.github/workflows/restrict-task-creation.yml b/.github/workflows/restrict-task-creation.yml
new file mode 100644
index 00000000000..da6fd831755
--- /dev/null
+++ b/.github/workflows/restrict-task-creation.yml
@@ -0,0 +1,67 @@
+---
+name: Restrict task creation
+
+# yamllint disable-line rule:truthy
+on:
+ issues:
+ types: [opened]
+
+jobs:
+ check-authorization:
+ runs-on: ubuntu-latest
+ # Only run if this is a Task issue type (from the issue form)
+ if: github.event.issue.type.name == 'Task'
+ steps:
+ - name: Check if user is authorized
+ uses: actions/github-script@v8
+ with:
+ script: |
+ const issueAuthor = context.payload.issue.user.login;
+
+ // Check if user is an organization member
+ try {
+ await github.rest.orgs.checkMembershipForUser({
+ org: 'home-assistant',
+ username: issueAuthor
+ });
+ console.log(`✅ ${issueAuthor} is an organization member`);
+ return; // Authorized
+ } catch (error) {
+ console.log(
+ `❌ ${issueAuthor} is not authorized to create Task issues`
+ );
+ }
+
+ // Close the issue with a comment
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: `Hi @${issueAuthor}, thank you for your contribution!\n\n` +
+ `Task issues are restricted to Open Home Foundation ` +
+ `staff and authorized contributors.\n\n` +
+ `If you would like to:\n` +
+ `- Report a bug: Please use the ` +
+ `[bug report form](https://github.com/home-assistant/` +
+ `addons/issues/new?template=bug_report.yml)\n` +
+ `- Request a feature: Please submit to ` +
+ `[Feature Requests](` +
+ `https://github.com/orgs/home-assistant/discussions)\n\n` +
+ `If you believe you should have access to create ` +
+ `Task issues, please contact the maintainers.`
+ });
+
+ await github.rest.issues.update({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ state: 'closed'
+ });
+
+ // Add a label to indicate this was auto-closed
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ labels: ['auto-closed']
+ });
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 067ad2e94d8..ef60e8636b4 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 30 days stale issues
- uses: actions/stale@v9.0.0
+ uses: actions/stale@v10.1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 30
diff --git a/README.md b/README.md
index 64bffcc197f..e8adef358be 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,17 @@
-# Home Assistant Add-ons: The official repository
+# Home Assistant Apps: The official repository
-Add-ons for Home Assistant allow you to extend the functionality
-around your Home Assistant setup. These add-ons can consist of an application
+Apps (formerly known as add-ons) for Home Assistant allow you to extend the functionality
+around your Home Assistant setup. These apps can consist of an application
that Home Assistant can integrate with (e.g., a [MQTT broker](/mosquitto/README.md) or [database server](/mariadb/README.md))
or allow access to your Home Assistant configuration (e.g., via [Samba](/samba/README.md) or using
the [File Editor](/configurator/README.md)).
-Add-ons can be installed and configured via the Home Assistant frontend on
+Apps can be installed and configured via the Home Assistant frontend on
systems that have installed Home Assistant.
-## Add-ons provided by this repository
+[](https://www.openhomefoundation.org/)
+
+## Apps provided by this repository
- **[CEC Scanner](/cec_scan/README.md)**
@@ -17,11 +19,7 @@ systems that have installed Home Assistant.
- **[deCONZ](/deconz/README.md)**
- Control a Zigbee network using ConBee or RaspBee hardware by Dresden Elektronik.
-
-- **[DHCP server](/dhcp_server/README.md)**
-
- A simple DHCP server.
+ Control a Zigbee network using ConBee or RaspBee hardware by dresden elektronik.
- **[Dnsmasq](/dnsmasq/README.md)**
@@ -39,13 +37,9 @@ systems that have installed Home Assistant.
Load and update configuration files for Home Assistant from a Git repository.
-- **[Google Assistant SDK](/google_assistant/README.md)**
-
- A virtual personal assistant developed by Google.
-
- **[Let's Encrypt](/letsencrypt/README.md)**
- Manage an create certificates from Let's Encrypt.
+ Manage and create certificates from Let's Encrypt.
- **[MariaDB](/mariadb/README.md)**
@@ -71,10 +65,6 @@ systems that have installed Home Assistant.
Allow logging in remotely to Home Assistant using SSH or just the web terminal with Ingress.
-- **[TellStick](/tellstick/README.md)**
-
- TellStick and TellStick Duo service.
-
- **[Z-Wave JS](/zwave_js/README.md)**
Allow Home Assistant to talk to a Z-Wave Network via a USB Controller.
@@ -91,11 +81,11 @@ You have several options to get them answered:
In case you've found a bug, please [open an issue on our GitHub][issue].
-## Developing your own add-ons
+## Developing your own apps
-In case you are interested in developing your own add-on, this
+In case you are interested in developing your own app, this
repository can be a great source of inspiration. For more information
-about developing an add-on, please see our
+about developing an app, please see our
[documentation for developers][dev-docs].
[discord]: https://discord.gg/c5DvZ4e
diff --git a/assist_microphone/CHANGELOG.md b/assist_microphone/CHANGELOG.md
index 1f52c81f7ad..927a0a5867c 100644
--- a/assist_microphone/CHANGELOG.md
+++ b/assist_microphone/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 1.3.0
+
+- Update to wyoming-satellite 1.3.0 to get support for timers
+- Added configuration options for setting timer sound, repetitions and delay
+
## 1.2.0
- Update to wyoming-satellite 1.2.0
diff --git a/assist_microphone/DOCS.md b/assist_microphone/DOCS.md
index 8dac481d27e..5c78fcaf597 100644
--- a/assist_microphone/DOCS.md
+++ b/assist_microphone/DOCS.md
@@ -4,7 +4,7 @@ Use [Assist](https://www.home-assistant.io/voice_control/) voice assistant with
## How to use
-After this add-on is installed and running, it will be automatically discovered
+After this app (formerly known as add-on) is installed and running, it will be automatically discovered
by the Wyoming integration in Home Assistant. To finish the setup,
click the following my button:
@@ -24,6 +24,18 @@ Path to WAV file to play when wake word is detected (empty to disable, default i
Path to WAV file to play when voice command is finished (empty to disable, default is `/usr/src/sounds/done.wav`).
+### Option: `timer_finished_wav`
+
+Path to WAV file to play when timer is finished (empty to disable, default is `/usr/src/sounds/timer_finished.wav`).
+
+### Option: `timer_repeat_count`
+
+Number of times to repeat `timer_finished_wav` (default is 3).
+
+### Option: `timer_repeat_delay`
+
+Delay before repeating `timer_finished_wav`, in seconds (default is 0.75).
+
### Option: `noise_suppression`
Noise suppression level (0 is disabled, 4 is max). Disabled by default.
diff --git a/assist_microphone/README.md b/assist_microphone/README.md
index 49c8f5de30d..df7739c5bf3 100644
--- a/assist_microphone/README.md
+++ b/assist_microphone/README.md
@@ -1,8 +1,8 @@
-# Home Assistant Add-on: Assist Microphone
+# Home Assistant App: Assist Microphone
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
-Home Assistant add-on that uses a local USB microphone to control [Assist](https://www.home-assistant.io/voice_control/).
+Home Assistant app (formerly known as add-on) that uses a local USB microphone to control [Assist](https://www.home-assistant.io/voice_control/).
Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/).
diff --git a/assist_microphone/build.yaml b/assist_microphone/build.yaml
index 92eecb36faf..1ab09e7b2a3 100644
--- a/assist_microphone/build.yaml
+++ b/assist_microphone/build.yaml
@@ -2,8 +2,5 @@
build_from:
amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
args:
- WYOMING_SATELLITE_VERSION: 1.2.0
+ WYOMING_SATELLITE_VERSION: 1.3.0
diff --git a/assist_microphone/config.yaml b/assist_microphone/config.yaml
index 4c703aaae8f..62dabbbd770 100644
--- a/assist_microphone/config.yaml
+++ b/assist_microphone/config.yaml
@@ -1,5 +1,5 @@
---
-version: 1.2.0
+version: 1.3.0
slug: assist_microphone
name: Assist Microphone
description: Use Assist with local microphone
@@ -16,6 +16,9 @@ map:
options:
awake_wav: "/usr/src/sounds/awake.wav"
done_wav: "/usr/src/sounds/done.wav"
+ timer_finished_wav: "/usr/src/sounds/timer_finished.wav"
+ timer_repeat_count: 3
+ timer_repeat_delay: 0.75
sound_enabled: true
noise_suppression: 0
auto_gain: 0
@@ -25,6 +28,9 @@ options:
schema:
awake_wav: str
done_wav: str
+ timer_finished_wav: str
+ timer_repeat_count: int
+ timer_repeat_delay: float
sound_enabled: bool
noise_suppression: int
auto_gain: int
diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish
index 438a276064a..8558b9a95ea 100755
--- a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish
+++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish
@@ -1,9 +1,11 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run
index 937e5f4c8d1..01aaedb7b5b 100755
--- a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run
+++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start service
@@ -19,6 +20,8 @@ exec python3 -m wyoming_satellite \
--snd-command-rate 16000 \
--awake-wav "$(bashio::config 'awake_wav')" \
--done-wav "$(bashio::config 'done_wav')" \
+ --timer-finished-wav "$(bashio::config 'timer_finished_wav')" \
+ --timer-finished-wav-repeat "$(bashio::config 'timer_repeat_count')" "$(bashio::config 'timer_repeat_delay')" \
--mic-volume-multiplier "$(bashio::config 'mic_volume_multiplier')" \
--snd-volume-multiplier "$(bashio::config 'sound_volume_multiplier')" \
--mic-auto-gain "$(bashio::config 'auto_gain')" \
diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
index 2f9de3a6daf..fa40eecd987 100755
--- a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
+++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Sends discovery information to Home Assistant.
diff --git a/assist_microphone/sounds/timer_finished.wav b/assist_microphone/sounds/timer_finished.wav
new file mode 100644
index 00000000000..40a97bca6c5
Binary files /dev/null and b/assist_microphone/sounds/timer_finished.wav differ
diff --git a/assist_microphone/translations/en.yaml b/assist_microphone/translations/en.yaml
index 41930951039..411674d7861 100644
--- a/assist_microphone/translations/en.yaml
+++ b/assist_microphone/translations/en.yaml
@@ -9,6 +9,19 @@ configuration:
description: >-
Path to WAV file to play when voice command is finished (empty to
disable).
+ timer_finished_wav:
+ name: Timer Finished WAV
+ description: >-
+ Path to WAV file to play when timer is finished (empty to disable,
+ default is /usr/src/sounds/timer_finished.wav).
+ timer_repeat_count:
+ name: Timer Finished WAV Repetition Count
+ description: >-
+ Number of times to repeat timer_finished_wav (default is 3).
+ timer_repeat_delay:
+ name: Timer Repetition Delay
+ description: >-
+ Delay before repeating timer_finished_wav, in seconds (default is 0.75).
noise_suppression:
name: Noise suppression
description: >-
diff --git a/cec_scan/DOCS.md b/cec_scan/DOCS.md
index 805b41b0e40..77abba5b1a5 100644
--- a/cec_scan/DOCS.md
+++ b/cec_scan/DOCS.md
@@ -1,19 +1,19 @@
-# Home Assistant Add-on: CEC Scanner
+# Home Assistant App: CEC Scanner
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "CEC Scanner" add-on and click it.
+1. Navigate in your Home Assistant frontend to **Settings** > **Apps** > **Install app**.
+2. Find the "CEC Scanner" app and click it.
3. Click on the "INSTALL" button.
## How to use
-This add-on has no configuration and runs out of the box.
+This app has no configuration and runs out of the box.
-1. Start the add-on.
-2. Check the add-on log output to see the result.
+1. Start the app.
+2. Check the app log output to see the result.
## Support
diff --git a/cec_scan/README.md b/cec_scan/README.md
index 13ceb431d8d..0e94aa08a4b 100644
--- a/cec_scan/README.md
+++ b/cec_scan/README.md
@@ -1,10 +1,10 @@
-# Home Assistant Add-on: CEC Scanner
+# Home Assistant App: CEC Scanner
Scan & discover HDMI CEC devices and their addresses.
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-This add-on allows for scanning for CEC devices. It is useful for finding
+This app (formerly known as add-on) allows for scanning for CEC devices. It is useful for finding
the CEC address of your devices.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/cec_scan/build.yaml b/cec_scan/build.yaml
index f7aeba897e4..39c55300242 100644
--- a/cec_scan/build.yaml
+++ b/cec_scan/build.yaml
@@ -5,8 +5,5 @@ build_from:
armhf: ghcr.io/home-assistant/armhf-base:3.14
armv7: ghcr.io/home-assistant/armv7-base:3.14
i386: ghcr.io/home-assistant/i386-base:3.14
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
args:
LIBCEC_VERSION: 6.0.2
diff --git a/cec_scan/rootfs/etc/services.d/cec-scan/finish b/cec_scan/rootfs/etc/services.d/cec-scan/finish
index 7459a7608d2..2e68f50bc41 100755
--- a/cec_scan/rootfs/etc/services.d/cec-scan/finish
+++ b/cec_scan/rootfs/etc/services.d/cec-scan/finish
@@ -1,4 +1,5 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service is done
# ==============================================================================
diff --git a/cec_scan/rootfs/etc/services.d/cec-scan/run b/cec_scan/rootfs/etc/services.d/cec-scan/run
index 953fa237213..4d27f510d9b 100755
--- a/cec_scan/rootfs/etc/services.d/cec-scan/run
+++ b/cec_scan/rootfs/etc/services.d/cec-scan/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start CEC scan service
# ==============================================================================
diff --git a/configurator/DOCS.md b/configurator/DOCS.md
index 0c840df2a60..547f1d5db93 100644
--- a/configurator/DOCS.md
+++ b/configurator/DOCS.md
@@ -1,25 +1,25 @@
-# Home Assistant Add-on: File editor
+# Home Assistant App: File editor
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "File editor" add-on and click it.
+1. Navigate in your Home Assistant frontend to **Settings** > **Apps** > **Install app**.
+2. Find the "File editor" app and click it.
3. Click on the "INSTALL" button.
## How to use
-In general, this add-on requires no configuration from your end.
+In general, this app requires no configuration from your end.
1. Toggle the "Show in sidebar" option, which adds the File editor to the main menu.
-2. Start the add-on.
+2. Start the app.
3. Refresh your browser, the "File editor" is now visible in the sidebar.
4. Click on the "File editor" menu option and start configuring!
## Configuration
-Add-on configuration:
+App configuration:
```yaml
dirsfirst: false
@@ -39,11 +39,11 @@ Set it to `true` to list directories first, `false` otherwise.
### Option: `enforce_basepath` (required)
If set to `true`, access is limited to files within the `/homeassistant` directory
-(also known as the `/config` folder inside Home Assisant itself).
+(also known as the `/config` folder inside Home Assistant itself).
### Option: `git` (required)
-If set to `true`, add-on will initialize git for directories which support it.
+If set to `true`, the app will initialize git for directories that support it.
### Option: `ignore_pattern` (required)
@@ -56,7 +56,7 @@ A list of filenames containing SSH private keys. These can be used to allow for
## Known issues and limitations
-- This add-on can only be used via Ingress and has no direct access.
+- This app can only be used via Ingress and has no direct access.
## Support
diff --git a/configurator/README.md b/configurator/README.md
index 76af7778b0e..8241685e503 100644
--- a/configurator/README.md
+++ b/configurator/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: File editor
+# Home Assistant App: File editor
Browser-based configuration file editor for Home Assistant.
@@ -26,7 +26,7 @@ configuration files) will be automatically checked for syntax errors while editi
- Restart Home Assistant directly with the click of a button. Reloading groups,
automations, etc. can be done as well. An API password is required.
- Direct links to Home Assistant documentation and icons.
-- Execute shell commands within the add-on container.
+- Execute shell commands within the app container.
- Editor settings are saved in your browser.
- And much more…
diff --git a/configurator/build.yaml b/configurator/build.yaml
index 9366f81e814..cafcee02c35 100644
--- a/configurator/build.yaml
+++ b/configurator/build.yaml
@@ -5,8 +5,5 @@ build_from:
armhf: ghcr.io/home-assistant/armhf-base:3.19
armv7: ghcr.io/home-assistant/armv7-base:3.19
i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
args:
CONFIGURATOR_VERSION: 0.5.2
diff --git a/configurator/config.yaml b/configurator/config.yaml
index b345c7efe27..25a03594e3c 100644
--- a/configurator/config.yaml
+++ b/configurator/config.yaml
@@ -4,7 +4,6 @@ slug: configurator
name: File editor
description: Simple browser-based file editor for Home Assistant
url: https://github.com/home-assistant/addons/tree/master/configurator
-codenotary: notary@home-assistant.io
arch:
- armhf
- armv7
diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish
index 438a276064a..8558b9a95ea 100755
--- a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish
+++ b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish
@@ -1,9 +1,11 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run
index e2ed3d64d10..37ab1afa586 100755
--- a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run
+++ b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run
@@ -1,4 +1,6 @@
#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start Configurator service
# ==============================================================================
diff --git a/configurator/translations/en.yaml b/configurator/translations/en.yaml
index 8beed56b080..bd661811b7c 100644
--- a/configurator/translations/en.yaml
+++ b/configurator/translations/en.yaml
@@ -13,8 +13,8 @@ configuration:
git:
name: Git
description: >-
- If set to `true`, add-on will initialize git for directories which support
- it.
+ If set to `true`, the app will initialize git for directories that
+ support it.
ignore_pattern:
name: Ignore Pattern
description: >-
diff --git a/deconz/CHANGELOG.md b/deconz/CHANGELOG.md
index 38e38e628b7..9cc42c7a2bf 100644
--- a/deconz/CHANGELOG.md
+++ b/deconz/CHANGELOG.md
@@ -1,5 +1,60 @@
# Changelog
+## 8.6.1
+
+- Align ingress colors with Home Assistant (toolbar color)
+
+## 8.6.0
+
+- Bump deCONZ to 2.32.5 [[CHANGELOG](https://github.com/dresden-elektronik/deconz-rest-plugin/releases/tag/v2.32.5)]
+- Renaming from add-on to app complete
+- HTTPS disabled
+
+## 8.5.3
+
+- Align ingress colors with Home Assistant (link color)
+
+## 8.5.2
+
+- Add configurable OTA update switches for Bosch, IKEA and OSRAM/LEDVANCE (default is off)
+- Add Bosch Smart Home OTA update script (Official repo)
+
+## 8.5.1
+
+- Add more debug options
+
+## 8.5.0
+
+- Fix discovery script
+
+## 8.4.0
+
+- Ingress entry page revised (for example, light and dark mode)
+- Update DOCS.md and a few naming corrections
+- Expand English translation
+
+## 8.3.0
+
+- Bump deCONZ to 2.31.2 [[CHANGELOG](https://github.com/dresden-elektronik/deconz-rest-plugin/releases/tag/v2.31.2)]
+
+## 8.2.0
+
+- Bump deCONZ to 2.30.2 [[CHANGELOG](https://github.com/dresden-elektronik/deconz-rest-plugin/releases/tag/v2.30.2)]
+
+## 8.1.0
+
+- Bump deCONZ to 2.29.5 [[CHANGELOG](https://github.com/dresden-elektronik/deconz-rest-plugin/releases/tag/v2.29.5)]
+
+## 8.0.0
+
+- Use openbox instead of dwm as window manager
+
+## 7.0.0
+
+- Bump deCONZ to 2.28.1
+- Use debian bookworm for all arch types
+- Use dwm instead of wmii as window manager
+
## 6.23.0
- Bump deCONZ to 2.25.3
@@ -23,7 +78,7 @@
## 6.18.0
- Bump deCONZ to 2.20.1
-
+
## 6.17.1
- Bump deCONZ to 2.19.3
diff --git a/deconz/DOCS.md b/deconz/DOCS.md
index f0ba649824c..2909078697c 100644
--- a/deconz/DOCS.md
+++ b/deconz/DOCS.md
@@ -1,11 +1,11 @@
-# Home Assistant Add-on: deCONZ
+# Home Assistant App: deCONZ
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "deCONZ" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "deCONZ" app and click it.
3. Click on the "INSTALL" button.
## How to use
@@ -22,52 +22,52 @@ enable_uart=1
dtoverlay=pi3-miniuart-bt
```
-### Configure the add-on
+### Configure the app
-The add-on needs to know where your ConBee/RaspBee can be found, and therefore,
-you'll need to configure the add-on to point to the right device.
+The app needs to know where your ConBee/RaspBee can be found, and therefore,
+you'll need to configure the app to point to the right device.
If you're using Home Assistant you may find the correct value for this on the
-`Settings -> System -> Hardware` page. It is recommended
+**Settings** -> **System** -> **Hardware** -> **All hardware** page. It is recommended
to use a "by-id" path to the device if one exists, as it is not subject to
change if other devices are added to the system.
-1. Replace `null` in the `device` option in the add-on configuration and specify
- the device name in quotes: e.g. something like
+1. Replace `null` in the `device` option in the app configuration and specify
+ the device name in quotes: e.g. something like
`"/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_XXXXXXXX-if00"`,
`"/dev/ttyUSB0"`, `"/dev/ttyAMA0"`, or `"/dev/ttyACM0"`.
-2. Click on "SAVE" to save the add-on configuration.
+2. Click on "SAVE" to save the app configuration.
3. Toggle the "Show in sidebar" to add it to your Home Assistant side bar.
-4. Start the add-on.
+4. Start the app.
-After installing and starting this add-on, access the deCONZ WebUI ("Phoscon")
-with "WEB UI" button.
+After installing and launching this app, you can select **deCONZ** under web UI to access
+the deCONZ GUI via VNC, or select **Phoscon** to configure the settings in the Phoscon App.
## Configuring the Home Assistant deCONZ integration
By default, Home Assistant has the `discovery` integration enabled, which
-automatically discovers this add-on.
+automatically discovers this app.
Navigate to **Settings** -> **Devices & Services** -> **Integrations** page after starting this
-add-on to configure the deCONZ integration.
+app to configure the deCONZ integration.
In case you don't have `discovery` enabled on your Home Assistant instance,
follow these instructions to configure the deCONZ integration:
-## Migrating to this Add-on
+## Migrating to this app
-To migrate deCONZ to Home Assistant and this add-on, backup your deCONZ config via the
-Phoscon WebUI, then restore that config after installing/reinstalling.
+To migrate deCONZ to Home Assistant and this app, back up your configuration via
+the Phoscon App and restore it after installation/reinstallation.
**_You must perform these steps or your Light, Group names and other data will be lost!_**
-However, your Zigbee devices will still paired to your ConBee or RaspBee hardware.
+However, your Zigbee devices will still be paired to your ConBee or RaspBee hardware.
## Accessing the deCONZ application and viewing the mesh via VNC
-The add-on allows you to access the underlying deCONZ application running on
+The app allows you to access the underlying deCONZ application running on
a remote desktop via VNC. It allows you to view the Zigbee mesh (which can
be really helpful when debugging network issues), but also gives you access
to tons of advanced features.
@@ -75,9 +75,9 @@ to tons of advanced features.
To enable it:
- Set a port number for VNC in the "Network" configuration section of the
- add-on and hit "SAVE". Advised is to use port 5900, but any other port above
+ app and hit "SAVE". Advised is to use port 5900, but any other port above
5900 works as well.
-- Restart the add-on.
+- Restart the app.
To access it, you need a [VNC Viewer][vnc-viewer] application. If you are using
macOS, you are in luck, since VNC is built-in. Open the spotlight search and
@@ -89,10 +89,9 @@ settings.
## Upgrading RaspBee and ConBee firmware
-This add-on allows you to upgrade your firmware straight from the Phoscon
-web interface with ease.
+This app allows you to upgrade your firmware straight from the Phoscon App with ease.
-Go to "Settings -> Gateway" and click the upgrade button.
+In the Phoscon App, go to **Settings** -> **Gateway**, then select the upgrade button.
However, some USB sticks (like the Aeotec Z-Wave sticks), can interfere with
the upgrade process, causing the firmware upgrade to fail silently. If you end
@@ -101,49 +100,52 @@ unplugging the other sticks and try again.
If that is still not working, try [upgrading the firmware manually][manual-upgrade].
-## Using the deCONZ/Phoscon API with another add-on
+## Using the deCONZ/Phoscon API with another app
-Some add-ons are capable of consuming the deCONZ API directly. Node-RED is
-one of those applications, that is available as an add-on, that can
+Some apps are capable of consuming the deCONZ API directly. Node-RED is
+one of those applications, that is available as an app, that can
consume the deCONZ API using the `node-red-contrib-deconz` node.
-**WARNING** Do not use the following settings to set up a integration manually
-from within Home Assistant!
+**WARNING:** Do not use these settings to set up an integration in Home Assistant.
-To allow these add-ons to connect to deCONZ, use the following settings:
+To allow these apps to connect to deCONZ, use the following settings:
- **Host**: `core-deconz`
- **(API) Port**: `40850`
- **WebSocket Port**: `8081`
-_Please note: the above settings are likely to change in a future update
-of this add-on._
+_Note: The above settings are likely to change in a future update of this app._
## Advanced debug output control
-Hidden controls are added to the add-on to allow control over the debug
+Hidden controls are added to the app to allow control over the debug
output of deCONZ. The following options are hidden, but can be added to
-the add-on configuration:
+the app configuration:
- `dbg_info`
- `dbg_aps`
-- `dbg_otau`
- `dbg_zcl`
- `dbg_zdp`
+- `dbg_ddf`
+- `dbg_dev`
+- `dbg_ota`
+- `dbg_error`
+- `dbg_http`
-These options require a number that represents the log level.
+These options require a number that represents the log level. The default value
+of `dbg_info` is 1 and all other debug options are 0.
-Example add-on config with `dbg_aps` enabled on log level 1:
+Example app config with `dbg_aps` enabled on log level L2:
```yaml
device: /dev/ttyUSB0
-dbg_aps: 1
+dbg_aps: 2
```
## Configuration
-Add-on configuration:
+App configuration:
```yaml
device: /dev/ttyAMA0
@@ -154,13 +156,14 @@ device: /dev/ttyAMA0
The device address of your ConBee/RaspBee.
If you're using Home Assistant you may find the correct value for this on the
-`Supervisor -> System -> Host system -> Hardware` page. It is recommended
+**Settings** -> **System** -> **Hardware** -> **All hardware** page. It is recommended
to use a "by-id" path to the device if one exists, as it is not subject to
change if other devices are added to the system.
In most cases this looks like one of the following:
-- `"/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_XXXXXXXX-if00"` (and similar for RaspBee and the original ConBee, replace `XXXXXXXX` with the value you see in your above mentioned hardware page)
+- `"/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_XXXXXXXX-if00"`
+ (and similar for RaspBee and the original ConBee, replace `XXXXXXXX` with the value you see in your above mentioned hardware page)
- `"/dev/ttyUSB0"`
- `"/dev/ttyAMA0"`
- `"/dev/ttyACM0"`
@@ -169,26 +172,25 @@ In most cases this looks like one of the following:
### My gateway shows up in Home Assistant with ID 0000000000000000
-This is an older bug that has been solved in the add-on. The add-on
+This is an older bug that has been solved in the app. The app
was too quick on sending the gateway ID in the past, before deCONZ had
one assigned.
This might cause issues in Home Assistant, like having no devices.
-It also might cause an issue when the add-on has internal changes and next
+It also might cause an issue when the app has internal changes and next
fails to communicate new settings to Home Assistant.
This can be solved by the following steps:
-1. Backup your deCONZ data, by going into the Web UI, from the menu choose:
- **Settings** -> **Gateway** -> **Backup Option** button, next create
+1. Backup your deCONZ/Phoscon data, by going into the Phoscon App, from the menu choose:
+ **Settings** -> **Gateway** -> **Backup options**, then create
a new backup and download it onto your computer.
-2. Uninstall the add-on.
+2. Uninstall the app.
3. In Home Assistant, remove the current integration you have for deCONZ.
4. Restart Home Assistant.
-5. Install the deCONZ add-on again, and configure it again according to the [instructions](#configure-the-add-on).
-6. Restore the backup you created at the first step at the same location
- in the Web UI as before.
-7. Restart the add-on and next, restart Home Assistant once more.
+5. Install the deCONZ app again, and configure it again according to the [instructions](#configure-the-app).
+6. Restore the backup you created at the first step at the same location in the Phoscon App as before.
+7. Restart the app and next, restart Home Assistant once more.
8. Follow the instructions on [setting up the deCONZ integration](#configuring-the-home-assistant-deconz-integration).
### My integration shows no devices after upgrading to 4.x
@@ -196,7 +198,7 @@ This can be solved by the following steps:
_Please, be sure you don't have the issue with gateway ID 0000000000000000._
It can happen that you have accidentally used an older discovery or a manual
-set up of the integration in the past. Because of this, the add-on is unable
+set up of the integration in the past. Because of this, the app is unable
to inform Home Assistant of changed internal settings, which happened in 4.x.
The solution for this is to do the following steps to take care of that issue
@@ -206,13 +208,13 @@ for once and for all, so in the future, you won't end up having this issue.
2. Restart Home Assistant.
3. Follow the instructions on [setting up the deCONZ integration](#configuring-the-home-assistant-deconz-integration).
-This will ensure you have a working integration and add-on for the future.
+This will ensure you have a working integration and app for the future.
## Known issues and limitations
- Use at least 2.5A power supply for your Raspberry Pi!
- This avoids strange behavior when using this add-on.
-- The add-on has no UPnP support.
+ This avoids strange behavior when using this app.
+- The app has no UPnP support.
- If for some reason the deCONZ frontend does not give you an initial setup
for your ConBee or RaspBee and keeps asking for a password, then most likely
`delight` is the default password you can use to get in.
@@ -235,5 +237,5 @@ In case you've found a bug, please [open an issue on our GitHub][issue].
[issue]: https://github.com/home-assistant/addons/issues
[manual-upgrade]: https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Update-deCONZ-manually
[reddit]: https://reddit.com/r/homeassistant
-[vnc-viewer]: https://bintray.com/tigervnc/stable/tigervnc/
+[vnc-viewer]: https://tigervnc.org
[vnc-service-url]: vnc://homeassistant.local:5900
diff --git a/deconz/Dockerfile b/deconz/Dockerfile
index 77be1453cce..6dd0713e783 100644
--- a/deconz/Dockerfile
+++ b/deconz/Dockerfile
@@ -11,6 +11,7 @@ RUN \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
+ openbox \
iproute2 \
iputils-ping \
kmod \
@@ -24,7 +25,7 @@ RUN \
libqt5widgets5 \
libqt5qml5 \
lsof \
- netcat \
+ netcat-traditional \
nginx \
novnc \
sqlite3 \
@@ -32,33 +33,9 @@ RUN \
tigervnc-standalone-server \
udev \
wget \
- wmii \
xfonts-base \
xfonts-scalable \
- && rm -rf /var/lib/apt/lists/* \
- && if [[ "armhf aarch64" = *"$BUILD_ARCH"* ]]; \
- then \
- apt-get update \
- && apt-get install -y --no-install-recommends \
- build-essential \
- git \
- && git clone --depth 1 https://github.com/WiringPi/WiringPi /usr/src/wiringpi \
- && cd /usr/src/wiringpi/wiringPi \
- && make \
- && make install \
- && cd ../devLib \
- && make \
- && make install \
- && cd ../gpio \
- && make \
- && make install \
- && apt-get purge -y --auto-remove \
- build-essential \
- git \
- && rm -rf \
- /var/lib/apt/lists/* \
- /usr/src/wiringpi; \
- fi
+ && rm -rf /var/lib/apt/lists/*
# Install deCONZ
ARG DECONZ_VERSION
@@ -79,3 +56,5 @@ RUN \
&& sed -i 's/\/root/\/data/' /etc/passwd
COPY rootfs /
+
+ENV S6_STAGE2_HOOK=/etc/s6-overlay/scripts/enable-check.sh
diff --git a/deconz/README.md b/deconz/README.md
index c8a485c9270..da71fead26f 100644
--- a/deconz/README.md
+++ b/deconz/README.md
@@ -1,8 +1,8 @@
-# Home Assistant Add-on: deCONZ
+# Home Assistant App: deCONZ
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-Control a Zigbee network using ConBee or RaspBee hardware by Dresden Elektronik.
+Control a Zigbee network using ConBee or RaspBee hardware by dresden elektronik.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
diff --git a/deconz/build.yaml b/deconz/build.yaml
index 5072ef8c9da..db95603cb45 100644
--- a/deconz/build.yaml
+++ b/deconz/build.yaml
@@ -1,10 +1,7 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base-debian:buster
- amd64: ghcr.io/home-assistant/amd64-base-debian:buster
- armhf: ghcr.io/home-assistant/armhf-base-raspbian:buster
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
+ amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
+ armhf: ghcr.io/home-assistant/armhf-base-raspbian:bookworm
args:
- DECONZ_VERSION: 2.25.3
+ DECONZ_VERSION: 2.32.5
diff --git a/deconz/config.yaml b/deconz/config.yaml
index 8727163ba55..d91c93bc316 100644
--- a/deconz/config.yaml
+++ b/deconz/config.yaml
@@ -1,9 +1,9 @@
---
-version: 6.23.0
+version: 8.6.1
slug: deconz
name: deCONZ
description: >-
- Control a Zigbee network with ConBee or RaspBee by Dresden Elektronik.
+ Control a Zigbee network with ConBee or RaspBee by dresden elektronik
url: https://github.com/home-assistant/addons/tree/master/deconz
apparmor: false
arch:
@@ -12,7 +12,6 @@ arch:
- aarch64
backup_exclude:
- "*/otau"
-codenotary: notary@home-assistant.io
devices:
- /dev/mem
discovery:
@@ -26,6 +25,10 @@ init: false
kernel_modules: true
options:
device: null
+ ota_update:
+ bosch: false
+ ikea: false
+ ledvance: false
panel_icon: mdi:zigbee
ports:
40850/tcp: null
@@ -35,11 +38,19 @@ privileged:
- SYS_RAWIO
schema:
device: device(subsystem=tty)
- dbg_aps: int?
- dbg_info: int?
- dbg_otau: int?
- dbg_zcl: int?
- dbg_zdp: int?
+ ota_update:
+ bosch: bool
+ ikea: bool
+ ledvance: bool
+ dbg_info: int(0,2)?
+ dbg_aps: int(0,2)?
+ dbg_zcl: int(0,1)?
+ dbg_zdp: int(0,1)?
+ dbg_ddf: int(0,1)?
+ dbg_dev: int(0,1)?
+ dbg_ota: int(0,1)?
+ dbg_error: int(0,2)?
+ dbg_http: int(0,1)?
startup: services
udev: true
usb: true
diff --git a/deconz/rootfs/etc/cont-init.d/firmware.sh b/deconz/rootfs/etc/cont-init.d/firmware.sh
index 8e0c23d524a..1254c356aa0 100755
--- a/deconz/rootfs/etc/cont-init.d/firmware.sh
+++ b/deconz/rootfs/etc/cont-init.d/firmware.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Manage deCONZ firmware
# ==============================================================================
diff --git a/deconz/rootfs/etc/cont-init.d/nginx.sh b/deconz/rootfs/etc/cont-init.d/nginx.sh
index 2f70a4c5011..66d8ca0b2e9 100755
--- a/deconz/rootfs/etc/cont-init.d/nginx.sh
+++ b/deconz/rootfs/etc/cont-init.d/nginx.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Configure NGINX for use with deCONZ
# ==============================================================================
diff --git a/deconz/rootfs/etc/cont-init.d/novnc.sh b/deconz/rootfs/etc/cont-init.d/novnc.sh
index c133526527a..6be4bc781f5 100755
--- a/deconz/rootfs/etc/cont-init.d/novnc.sh
+++ b/deconz/rootfs/etc/cont-init.d/novnc.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Setup noVNC
# ==============================================================================
diff --git a/deconz/rootfs/etc/s6-overlay/scripts/enable-check.sh b/deconz/rootfs/etc/s6-overlay/scripts/enable-check.sh
new file mode 100755
index 00000000000..4ad367f8494
--- /dev/null
+++ b/deconz/rootfs/etc/s6-overlay/scripts/enable-check.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Custom S6 stage2 hook — runs before services.d start
+# ==============================================================================
+if ! bashio::config.true 'ota_update.bosch'; then
+ bashio::log.info "Bosch OTA update is disabled."
+ rm -rf /etc/services.d/otau-bosch
+fi
+
+if ! bashio::config.true 'ota_update.ikea'; then
+ bashio::log.info "IKEA OTA update is disabled."
+ rm -rf /etc/services.d/otau-ikea
+fi
+
+if ! bashio::config.true 'ota_update.ledvance'; then
+ bashio::log.info "OSRAM/LEDVANCE OTA update is disabled."
+ rm -rf /etc/services.d/otau-ledvance
+fi
diff --git a/deconz/rootfs/etc/services.d/deconz/discovery b/deconz/rootfs/etc/services.d/deconz/discovery
index 96cd7690a92..9af1401bd92 100755
--- a/deconz/rootfs/etc/services.d/deconz/discovery
+++ b/deconz/rootfs/etc/services.d/deconz/discovery
@@ -1,14 +1,16 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Send deCONZ discovery information to Home Assistant
# ==============================================================================
-readonly DATA_STORE="/data/.local/share/dresden-elektronik/deCONZ/zll.db"
declare api_key
declare config
-declare query
declare retries
declare serial
+bashio::log.info "Starting discovery script..."
+
# Wait for deCONZ to start before continuing
bashio::net.wait_for 40850
@@ -18,42 +20,78 @@ if bashio::fs.file_exists /data/hassio.json; then
rm /data/hassio.json
fi
-# Try to get API key from deCONZ database
-query='SELECT apikey FROM auth WHERE devicetype="Home Assistant" ORDER BY createdate DESC LIMIT 1'
-api_key=$(sqlite3 "${DATA_STORE}" "${query}" .exit)
-if ! bashio::var.has_value "${api_key}"; then
- # Register an API key for Home Assistant
- if ! result="$(curl --silent --show-error --request POST -d '{"devicetype": "Home Assistant"}' "http://127.0.0.1:40850/api")";
- then
- bashio::log.debug "${result}"
- bashio::exit.nok "Can't get API key from deCONZ gateway"
+# Locate database
+DATA_STORE="/data/.local/share/deCONZ/zll.db"
+if [ ! -f "$DATA_STORE" ]; then
+ bashio::log.warning "Database not found at $DATA_STORE, trying alternative path..."
+ DATA_STORE="/data/.local/share/dresden-elektronik/deCONZ/zll.db"
+ if [ ! -f "$DATA_STORE" ]; then
+ bashio::log.error "No database found in either path! Proceeding without serial."
+ DATA_STORE=""
fi
- api_key="$(bashio::jq "${result}" '.[0].success.username')"
fi
-# Try to get the bridge ID/serial, try to avoid using 0000000000000000
-retries=25
-serial="0000000000000000"
-while [[ "${serial}" = "0000000000000000" ]]; do
- bashio::log.debug "Waiting for bridge ID..."
- sleep 10
+# Read API key from database
+if [ -n "$DATA_STORE" ]; then
+ api_key=$(sqlite3 "${DATA_STORE}" \
+ 'SELECT apikey FROM auth WHERE devicetype="Home Assistant" ORDER BY createdate DESC LIMIT 1' 2>/dev/null)
+fi
- # If we tried 25 times, just abort.
- if [[ "${retries}" -eq 0 ]]; then
- bashio::exit.nok "Failed to get a valid bridge ID. Discovery aborted."
+# Test API key immediately, if available
+if [ -n "$api_key" ]; then
+ http_code=$(curl -s -o /dev/null -w "%{http_code}" \
+ "http://127.0.0.1:40850/api/${api_key}/config")
+ if [[ "$http_code" != "200" ]]; then
+ bashio::log.warning "Existing API key invalid (HTTP $http_code), will try to create a new one..."
+ api_key=""
+ else
+ bashio::log.info "Existing API key is valid."
fi
+fi
- # Get bridge ID from API
- if ! result="$(curl --silent --show-error --request GET "http://127.0.0.1:40850/api/${api_key}/config")";
- then
- bashio::log.debug "${result}"
- bashio::exit.nok "Can't get data from deCONZ gateway"
+# Try to create API key if none exists
+if ! bashio::var.has_value "${api_key}"; then
+ bashio::log.warning "No API key found – trying to create a new one..."
+ for i in $(seq 1 60); do
+ if result="$(curl --silent --show-error --request POST \
+ -d '{"devicetype": "Home Assistant"}' \
+ "http://127.0.0.1:40850/api")"; then
+ api_key="$(bashio::jq "${result}" '.[0].success.username')"
+ if bashio::var.has_value "${api_key}"; then
+ bashio::log.info "API key successfully created after ${i} seconds."
+ break
+ fi
+ fi
+ sleep 1
+ done
+ if ! bashio::var.has_value "${api_key}"; then
+ bashio::log.error "Failed to get an API key from deCONZ – continuing without discovery."
+ exit 0
fi
- serial="$(bashio::jq "${result}" '.bridgeid')"
+fi
+# Get serial/bridge ID
+retries=25
+serial="0000000000000000"
+while [[ "${serial}" = "0000000000000000" && "${retries}" -gt 0 ]]; do
+ sleep 5
+ if result="$(curl --silent --show-error \
+ --request GET "http://127.0.0.1:40850/api/${api_key}/config")"; then
+ candidate="$(bashio::jq "${result}" '.bridgeid')"
+ if [[ "$candidate" =~ ^[0-9A-Fa-f]{16}$ ]]; then
+ serial="$candidate"
+ else
+ serial="0000000000000000"
+ fi
+ fi
((retries--))
done
+if [[ "${serial}" = "0000000000000000" ]]; then
+ bashio::log.error "Failed to get a valid bridge ID – continuing without discovery."
+ exit 0
+fi
+
# Create config payload for Home Assistant
config=$(bashio::var.json \
host "$(hostname)" \
@@ -64,7 +102,7 @@ config=$(bashio::var.json \
# Send discovery info
if bashio::discovery "deconz" "${config}" > /dev/null; then
- bashio::log.info "Successfully send discovery information to Home Assistant."
+ bashio::log.info "Successfully sent discovery information to Home Assistant."
else
- bashio::log.error "Discovery message to Home Assistant failed!"
+ bashio::log.error "Failed to send discovery message to Home Assistant!"
fi
diff --git a/deconz/rootfs/etc/services.d/deconz/finish b/deconz/rootfs/etc/services.d/deconz/finish
index 5a23d05348c..f18f83626d1 100755
--- a/deconz/rootfs/etc/services.d/deconz/finish
+++ b/deconz/rootfs/etc/services.d/deconz/finish
@@ -1,11 +1,12 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/deconz/rootfs/etc/services.d/deconz/run b/deconz/rootfs/etc/services.d/deconz/run
index 1e8685e11e4..57edda5c641 100755
--- a/deconz/rootfs/etc/services.d/deconz/run
+++ b/deconz/rootfs/etc/services.d/deconz/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start deCONZ service
# ==============================================================================
@@ -33,7 +35,7 @@ fi
export XDG_RUNTIME_DIR="${TMP_FOLDER}"
export DISPLAY=":0"
-bashio::log.info "Starting VNC server (local/${LOCAL_ONLY})..."
+bashio::log.info "Starting VNC server (local - ${LOCAL_ONLY})..."
tigervncserver \
-name "Home Assistant - deCONZ" \
-geometry 1920x1080 \
@@ -48,17 +50,32 @@ tigervncserver \
bashio::log.info "deCONZ waiting for VNC to start"
bashio::net.wait_for 5900
+# Delete unused key
+options=$(bashio::addon.options)
+if bashio::jq.exists "${options}" ".dbg_otau"; then
+ bashio::log.info "Removing dbg_otau"
+ bashio::addon.option "dbg_otau"
+fi
+
# Load debug values
bashio::config.has_value 'dbg_info' \
&& DBG_INFO="$(bashio::config 'dbg_info')" || DBG_INFO=1
bashio::config.has_value 'dbg_aps' \
&& DBG_APS="$(bashio::config 'dbg_aps')" || DBG_APS=0
-bashio::config.has_value 'dbg_otau' \
- && DBG_OTAU="$(bashio::config 'dbg_otau')" || DBG_OTAU=0
bashio::config.has_value 'dbg_zcl' \
&& DBG_ZCL="$(bashio::config 'dbg_zcl')" || DBG_ZCL=0
bashio::config.has_value 'dbg_zdp' \
&& DBG_ZDP="$(bashio::config 'dbg_zdp')" || DBG_ZDP=0
+bashio::config.has_value 'dbg_ddf' \
+ && DBG_DDF="$(bashio::config 'dbg_ddf')" || DBG_DDF=0
+bashio::config.has_value 'dbg_dev' \
+ && DBG_DEV="$(bashio::config 'dbg_dev')" || DBG_DEV=0
+bashio::config.has_value 'dbg_ota' \
+ && DBG_OTA="$(bashio::config 'dbg_ota')" || DBG_OTA=0
+bashio::config.has_value 'dbg_error' \
+ && DBG_ERROR="$(bashio::config 'dbg_error')" || DBG_ERROR=0
+bashio::config.has_value 'dbg_http' \
+ && DBG_HTTP="$(bashio::config 'dbg_http')" || DBG_HTTP=0
# Send out discovery information to Home Assistant
./discovery &
@@ -70,10 +87,15 @@ exec deCONZ \
--auto-connect=1 \
--dbg-info="${DBG_INFO}" \
--dbg-aps="${DBG_APS}" \
- --dbg-otau="${DBG_OTAU}" \
--dbg-zcl="${DBG_ZCL}" \
--dbg-zdp="${DBG_ZDP}" \
+ --dbg-ddf="${DBG_DDF}" \
+ --dbg-dev="${DBG_DEV}" \
+ --dbg-ota="${DBG_OTA}" \
+ --dbg-error="${DBG_ERROR}" \
+ --dbg-http="${DBG_HTTP}" \
--upnp=0 \
--http-port=40850 \
+ --https-port=0 \
--ws-port=8081 \
--dev="${DECONZ_DEVICE}"
diff --git a/deconz/rootfs/etc/services.d/nginx/finish b/deconz/rootfs/etc/services.d/nginx/finish
index 5a23d05348c..f18f83626d1 100755
--- a/deconz/rootfs/etc/services.d/nginx/finish
+++ b/deconz/rootfs/etc/services.d/nginx/finish
@@ -1,11 +1,12 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/deconz/rootfs/etc/services.d/nginx/run b/deconz/rootfs/etc/services.d/nginx/run
index 38ef478552e..e98c4571ac5 100755
--- a/deconz/rootfs/etc/services.d/nginx/run
+++ b/deconz/rootfs/etc/services.d/nginx/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start NGINX service
# ==============================================================================
diff --git a/deconz/rootfs/etc/services.d/otau-bosch/run b/deconz/rootfs/etc/services.d/otau-bosch/run
new file mode 100755
index 00000000000..e2f9894c145
--- /dev/null
+++ b/deconz/rootfs/etc/services.d/otau-bosch/run
@@ -0,0 +1,62 @@
+#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# Download available firmware update for Bosch Smart Home (*.fw)
+# ==============================================================================
+readonly REPO="BoschSmartHome/bosch-smart-home-files"
+readonly API_BASE="https://api.github.com/repos/${REPO}/contents/firmware-otau-files"
+
+# Ensure OTAU folder exists
+mkdir -p "/data/otau"
+
+bashio::log.info "Running the Bosch OTA updater..."
+
+# Fetch GitHub firmware data
+if ! curl -fsL "${API_BASE}" >/dev/null; then
+ bashio::log.warning "⚠️ Can't fetch data from GitHub — retry in 5 hours."
+ exec sleep 18000
+fi
+
+fetch_fw_files() {
+ local api_url
+ api_url="$1"
+
+ local data
+ data=$(curl -s "$api_url")
+
+ # Some GitHub responses return a single object instead of an array
+ [[ $(echo "$data" | jq -r 'type') == "object" ]] && data="[$data]"
+
+ echo "$data" | jq -r '.[] | @base64' | while read -r entry; do
+ _jq() { echo "$entry" | base64 --decode | jq -r "$1"; }
+
+ local type
+ type=$(_jq '.type')
+ local name
+ name=$(_jq '.name')
+ local path
+ path=$(_jq '.path')
+ local download_url
+ download_url=$(_jq '.download_url')
+
+ if [[ "$type" == "dir" ]]; then
+ # Recursive call for subfolders
+ local encoded_path
+ encoded_path=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''${path}''', safe=''))")
+ fetch_fw_files "https://api.github.com/repos/${REPO}/contents/${encoded_path}?ref=main"
+ elif [[ "$name" == *.fw && -n "$download_url" ]]; then
+ local target
+ target="/data/otau/${name}"
+
+ # Skip already downloaded files
+ [[ -f "${target}" ]] && continue
+
+ # Download firmware
+ curl -s -L -o "${target}" "${download_url}"
+ fi
+ done
+}
+fetch_fw_files "${API_BASE}"
+
+exec sleep 259200 # Sleep for 3 days before next check
diff --git a/deconz/rootfs/etc/services.d/otau-deconz/run b/deconz/rootfs/etc/services.d/otau-deconz/run
deleted file mode 100755
index 109535eb7bd..00000000000
--- a/deconz/rootfs/etc/services.d/otau-deconz/run
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# ==============================================================================
-# Download available firmware update for IKEA
-# ==============================================================================
-
-# Start OTA updates for deCONZ
-bashio::log.info "Running the deCONZ OTA updater..."
-deCONZ-otau-dl.sh &> /dev/null
-
-exec sleep 259200
diff --git a/deconz/rootfs/etc/services.d/otau-ikea/run b/deconz/rootfs/etc/services.d/otau-ikea/run
index 922a063440e..4139c3ce648 100755
--- a/deconz/rootfs/etc/services.d/otau-ikea/run
+++ b/deconz/rootfs/etc/services.d/otau-ikea/run
@@ -1,33 +1,36 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Download available firmware update for IKEA
# ==============================================================================
readonly URL_IKEA="http://fw.ota.homesmart.ikea.net/feed/version_info.json"
-# Ensure otau folder exists
+# Ensure OTAU folder exists
mkdir -p "/data/otau"
bashio::log.info "Running the IKEA OTA updater..."
+# Fetch IKEA firmware data
if ! IKEA_DATA="$(curl -sL ${URL_IKEA})"; then
- bashio::log.info "Can't fetch data from ikea!"
+ bashio::log.warning "⚠️ Can't fetch data from IKEA — retry in 5 hours."
exec sleep 18000
fi
+# Process each firmware entry
IKEA_DATA_SIZE="$(echo "${IKEA_DATA}" | jq --raw-output '. | length')"
-for (( i=0; i < "${IKEA_DATA_SIZE}"; i++ )); do
+for (( i=0; i < IKEA_DATA_SIZE; i++ )); do
OTAU_URL=$(echo "${IKEA_DATA}" | jq --raw-output ".[$i].fw_binary_url // empty")
+ OTAU_FILE="/data/otau/${OTAU_URL##*/}"
- if [ -z "${OTAU_URL}" ]; then
- continue
- fi
+ # Skip empty URLs
+ [[ -z "${OTAU_URL}" ]] && continue
- OTAU_FILE="/data/otau/${OTAU_URL##*/}"
- if [ -f "${OTAU_FILE}" ]; then
- continue
- fi
+ # Skip already downloaded files
+ [[ -f "${OTAU_FILE}" ]] && continue
+ # Download firmware
curl -s -L -o "${OTAU_FILE}" "${OTAU_URL}"
done
-exec sleep 259200
+exec sleep 266400 # Sleep for 3 days 2 hours before next check
diff --git a/deconz/rootfs/etc/services.d/otau-ledvance/run b/deconz/rootfs/etc/services.d/otau-ledvance/run
index 1697f39aa48..cabbeaffa60 100755
--- a/deconz/rootfs/etc/services.d/otau-ledvance/run
+++ b/deconz/rootfs/etc/services.d/otau-ledvance/run
@@ -1,39 +1,39 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
-# Download available firmware update for OSRAM Ledvance
+# Download available firmware update for OSRAM/LEDVANCE
# ==============================================================================
readonly URL_OSRAM="https://api.update.ledvance.com/v1/zigbee/firmwares"
-# Ensure otau folder exists
+# Ensure OTAU folder exists
mkdir -p "/data/otau"
-bashio::log.info "Running the OSRAM LEdvance OTA updater..."
+bashio::log.info "Running the OSRAM/LEDVANCE OTA updater..."
-# fetch data
+# Fetch OSRAM/LEDVANCE firmware data
if ! OSRAM_DATA="$(curl -sL ${URL_OSRAM})"; then
- bashio::log.info "Can't fetch data from osram!"
+ bashio::log.warning "⚠️ Can't fetch data from OSRAM/LEDVANCE — retry in 5 hours."
exec sleep 18000
fi
OSRAM_DATA_SIZE="$(echo "${OSRAM_DATA}" | jq --raw-output '.firmwares | length')"
-DL_DONE=0
-for (( i=0; i < "${OSRAM_DATA_SIZE}"; i++ )); do
+for (( i=0; i < OSRAM_DATA_SIZE; i++ )); do
OSRAM_COMPANY=$( echo "${OSRAM_DATA}" | jq --raw-output ".firmwares[$i].identity.company // empty" 2>/dev/null)
OSRAM_PRODUCT=$( echo "${OSRAM_DATA}" | jq --raw-output ".firmwares[$i].identity.product // empty" 2>/dev/null)
OTAU_FILENAME=$( echo "${OSRAM_DATA}" | jq --raw-output ".firmwares[$i].name // empty" 2>/dev/null)
- OTAU_URL="$URL_OSRAM/download/${OSRAM_COMPANY}/${OSRAM_PRODUCT}/latest"
-
+ OTAU_URL="$URL_OSRAM/download/${OSRAM_COMPANY}/${OSRAM_PRODUCT}/latest"
OTAU_FILE="/data/otau/${OTAU_FILENAME}"
- if [ -e "${OTAU_FILE}" ]; then
- continue
- fi
+
+ # Skip empty file names
+ [[ -z "${OTAU_FILENAME}" ]] && continue
+
+ # Skip already downloaded files
+ [[ -e "${OTAU_FILE}" ]] && continue
+
+ # Download firmware
curl -s -L -o "${OTAU_FILE}" "${OTAU_URL}" || true
- ((DL_DONE+1))
- if [ "$((DL_DONE % 10))" == "0" ]; then
- # LEDVANCE/OSRAM API RateLimits : The rate limit 10 calls per 60 seconds or quota 100 MB per month.
- DL_DONE=0
- sleep 65
- fi
+ sleep 5 # OSRAM/LEDVANCE API rate limits: The limit is 30 requests per minute.
done
-exec sleep 259200
+exec sleep 273600 # Sleep for 3 days 4 hours before next check
diff --git a/deconz/rootfs/etc/services.d/websockify/run b/deconz/rootfs/etc/services.d/websockify/run
index d75921d60b9..db2eb43503b 100755
--- a/deconz/rootfs/etc/services.d/websockify/run
+++ b/deconz/rootfs/etc/services.d/websockify/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start ozw-admin
# ==============================================================================
diff --git a/deconz/rootfs/usr/share/www/ingress.html b/deconz/rootfs/usr/share/www/ingress.html
index a47be0028a1..11a0540b66a 100644
--- a/deconz/rootfs/usr/share/www/ingress.html
+++ b/deconz/rootfs/usr/share/www/ingress.html
@@ -1,306 +1,273 @@
-
+
+
diff --git a/deconz/translations/en.yaml b/deconz/translations/en.yaml
index 8672c154c49..ff22a82288b 100644
--- a/deconz/translations/en.yaml
+++ b/deconz/translations/en.yaml
@@ -3,17 +3,40 @@ configuration:
device:
name: Device
description: The device address of your ConBee/RaspBee.
- dbg_aps:
- name: Debug aps
dbg_info:
- name: Debug info
- dbg_otau:
- name: Debug otau
+ name: Debug Info
+ dbg_aps:
+ name: Debug APS
dbg_zcl:
- name: Debug zcl
+ name: Debug ZCL
dbg_zdp:
- name: Debug zdp
+ name: Debug ZDP
+ dbg_ddf:
+ name: Debug DDF
+ dbg_dev:
+ name: Debug DEV
+ dbg_ota:
+ name: Debug OTA
+ dbg_error:
+ name: Debug Error
+ dbg_http:
+ name: Debug HTTP
+ ota_update:
+ name: Zigbee OTA updates
+ description: >-
+ Automatically downloads available Zigbee firmware updates when
+ enabled.
+ fields:
+ bosch:
+ name: Bosch
+ ikea:
+ name: IKEA
+ ledvance:
+ name: OSRAM/LEDVANCE
network:
- 40850/tcp: deCONZ API backend (Not required for Ingress)
- 5900/tcp: deCONZ via VNC (Not required for Ingress. Not secure!)
- 8081/tcp: deCONZ WebSocket (Not required for Ingress)
+ 40850/tcp: >-
+ deCONZ API backend (Access for Phoscon and REST API outside the app)
+ 5900/tcp: >-
+ deCONZ via VNC (Accessing the GUI with external VNC software. Not secured!)
+ 8081/tcp: >-
+ deCONZ WebSocket (Connection to other applications e.g. Node-RED)
diff --git a/dhcp_server/CHANGELOG.md b/dhcp_server/CHANGELOG.md
deleted file mode 100644
index 7f2b0aa3d7e..00000000000
--- a/dhcp_server/CHANGELOG.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Changelog
-
-## 1.4.0
-
-- Update base image to alpine 3.19
-
-## 1.3.1
-
-- Don't fail if no DNS is provided
-
-## 1.3.0
-
-- Add NTP server configuration option.
-
-## 1.2
-
-- Fixes crash when using FQDN as domain
-
-## 1.1
-
-- Rewrite add-on onto Bashio
-- Added documentation to add-on repository
-- Small changes to code styling
-
-## 1.0
-
-- Update DHCP to 4.4.1
diff --git a/dhcp_server/DOCS.md b/dhcp_server/DOCS.md
deleted file mode 100644
index 80beb7da508..00000000000
--- a/dhcp_server/DOCS.md
+++ /dev/null
@@ -1,151 +0,0 @@
-# Home Assistant Add-on: DHCP server
-
-## Installation
-
-Follow these steps to get the add-on installed on your system:
-
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "DHCP server" add-on and click it.
-3. Click on the "INSTALL" button.
-4. Modify configuration as needed
-
-## How to use
-
-1. Set the `domain` option, e.g., `mynetwork.local`.
-2. Save the add-on configuration by clicking the "SAVE" button.
-3. Start the add-on.
-
-## Configuration
-
-The DHCP server add-on can be tweaked to your likings. This section
-describes each of the add-on configuration options.
-
-Example add-on configuration:
-
-```yaml
-domain: mynetwork.local
-dns:
- - 8.8.8.8
- - 8.8.4.4
-ntp:
- - 192.168.1.0
-default_lease: 86400
-max_lease: 172800
-networks:
- - subnet: 192.168.1.0
- netmask: 255.255.255.0
- range_start: 192.168.1.100
- range_end: 192.168.1.200
- broadcast: 192.168.1.255
- gateway: 192.168.1.1
- interface: eth0
-hosts:
- - name: webcam_xy
- mac: aa:bb:ee:cc
- ip: 192.168.1.40
-```
-
-### Option: `domain` (required)
-
-Your network domain name, e.g., `mynetwork.local` or `home.local`
-
-### Option: `dns` (required)
-
-The DNS servers your DHCP server gives to your clients. This option can
-contain a list of servers. By default, it is configured to have Google's
-public DNS servers: `"8.8.8.8", "8.8.4.4".
-
-### Option `ntp` (required)
-
-The NTP servers your DHCP server gives to your clients. This option can
-contain a list of server. By default, none are configured ([])
-
-### Option: `default_lease` (required)
-
-The default time in seconds that the IP is leased to your client.
-Defaults to `86400`, which is one day.
-
-### Option: `max_lease` (required)
-
-The max time in seconds that the IP is leased to your client.
-Defaults to `172800`, which is two days.
-
-### Option: `networks` (one item required)
-
-This option defines settings for one or multiple networks for the DHCP server
-to hand out IP addresses for.
-
-At least one network definition in your configuration is required for the
-DHCP server to work.
-
-#### Option: `networks.subnet`
-
-Your network schema/subnet. For example, if your IP addresses are `192.168.1.x`
-the subnet becomes `192.168.1.0`.
-
-#### Option: `networks.netmask`
-
-Your network netmask. For example, if your IP addresses are `192.168.1.x` the
-netmask becomes `255.255.255.0`.
-
-#### Option: `networks.range_start`
-
-Defines the start IP address for the DHCP server to lease IPs for.
-Use this together with the `range_end` option to define the range of IP
-addresses the DHCP server operates in.
-
-#### Option: `networks.range_end`
-
-Defines the end IP address for the DHCP server to lease IPs for.
-
-#### Option: `networks.broadcast`
-
-The broadcast address specific to the lease range. For example, if your
-IP addresses are `192.168.1.x`, the broadcast address is usually `192.168.1.255`.
-
-#### Option: `networks.gateway`
-
-Sets the gateway address for that the DHCP server hands out to its clients.
-This is usually the IP address of your router.
-
-#### Option: `networks.interface`
-
-The network interface to listen to for this network, e.g., `eth0`.
-
-### Option: `hosts` (optional)
-
-This option defines settings for one or host definitions for the DHCP server.
-
-It allows you to fix a host to a specific IP address.
-
-By default, non are configured.
-
-#### Option: `hosts.name`
-
-The name of the hostname you'd like to fix an address for.
-
-#### Option: `hosts.mac`
-
-The MAC address of the client device.
-
-#### Option: `hosts.ip`
-
-The IP address you want the DHCP server to assign.
-
-## Support
-
-Got questions?
-
-You have several options to get them answered:
-
-- The [Home Assistant Discord Chat Server][discord].
-- The Home Assistant [Community Forum][forum].
-- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
-
-In case you've found a bug, please [open an issue on our GitHub][issue].
-
-[discord]: https://discord.gg/c5DvZ4e
-[forum]: https://community.home-assistant.io
-[issue]: https://github.com/home-assistant/addons/issues
-[reddit]: https://reddit.com/r/homeassistant
-[repository]: https://github.com/hassio-addons/repository
diff --git a/dhcp_server/Dockerfile b/dhcp_server/Dockerfile
deleted file mode 100644
index c7fb74da5a8..00000000000
--- a/dhcp_server/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-ARG BUILD_FROM
-FROM $BUILD_FROM
-
-# Add env
-ENV LANG C.UTF-8
-
-# Setup base
-RUN apk add --no-cache dhcp
-
-# Copy data
-COPY data/run.sh /
-
-CMD [ "/run.sh" ]
diff --git a/dhcp_server/README.md b/dhcp_server/README.md
deleted file mode 100644
index 834278f0195..00000000000
--- a/dhcp_server/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Home Assistant Add-on: DHCP server
-
-A simple DHCP server.
-
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-
-This add-on provides a simple DHCP server for your network.
-It provides some basic needs, like, reserving IP addresses for your devices
-to ensure they always get assigned the same IP address.
-
-[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
-[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
diff --git a/dhcp_server/build.yaml b/dhcp_server/build.yaml
deleted file mode 100644
index 039821f92e6..00000000000
--- a/dhcp_server/build.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armhf: ghcr.io/home-assistant/armhf-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
diff --git a/dhcp_server/config.yaml b/dhcp_server/config.yaml
deleted file mode 100644
index 62b0dadd56e..00000000000
--- a/dhcp_server/config.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
----
-version: 1.4.0
-slug: dhcp_server
-name: DHCP server
-description: A simple DHCP server
-url: https://home-assistant.io/addons/dhcp_server/
-codenotary: notary@home-assistant.io
-advanced: true
-arch:
- - armhf
- - armv7
- - aarch64
- - amd64
- - i386
-host_network: true
-image: homeassistant/{arch}-addon-dhcp_server
-options:
- default_lease: 86400
- dns:
- - 8.8.8.8
- - 8.8.4.4
- ntp: []
- domain: null
- hosts: []
- max_lease: 172800
- networks:
- - broadcast: 192.168.1.255
- gateway: 192.168.1.1
- interface: eth0
- netmask: 255.255.255.0
- range_end: 192.168.1.200
- range_start: 192.168.1.100
- subnet: 192.168.1.0
-schema:
- default_lease: int
- dns:
- - str
- ntp:
- - str
- domain: str
- hosts:
- - ip: str
- mac: str
- name: str
- max_lease: int
- networks:
- - broadcast: str
- gateway: str
- interface: str
- netmask: str
- range_end: str
- range_start: str
- subnet: str
-startup: system
-init: false
diff --git a/dhcp_server/data/run.sh b/dhcp_server/data/run.sh
deleted file mode 100755
index ff0b89871dc..00000000000
--- a/dhcp_server/data/run.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/with-contenv bashio
-set -e
-
-CONFIG="/etc/dhcpd.conf"
-LEASES="/data/dhcpd.lease"
-
-bashio::log.info "Creating DHCP configuration..."
-
-# Create main config
-DEFAULT_LEASE=$(bashio::config 'default_lease')
-DOMAIN=$(bashio::config 'domain')
-MAX_LEASE=$(bashio::config 'max_lease')
-
-{
- echo "option domain-name \"${DOMAIN}\";"
- echo "default-lease-time ${DEFAULT_LEASE};"
- echo "max-lease-time ${MAX_LEASE};"
- echo "authoritative;"
-} > "${CONFIG}"
-
-# Create DNS Server List
-if [ "$(bashio::config 'dns')" ]
-then
- DNS=$(bashio::config 'dns|join(", ")')
- {
- echo "option domain-name-servers ${DNS};";
- } >> "${CONFIG}"
-fi
-
-
-# Create NTP Server List
-if [ "$(bashio::config 'ntp')" ]
-then
- NTP=$(bashio::config 'ntp|join(", ")')
- {
- echo "option ntp-servers ${NTP};";
- } >> "${CONFIG}"
-fi
-
-# Create networks
-for network in $(bashio::config 'networks|keys'); do
- BROADCAST=$(bashio::config "networks[${network}].broadcast")
- GATEWAY=$(bashio::config "networks[${network}].gateway")
- INTERFACE=$(bashio::config "networks[${network}].interface")
- NETMASK=$(bashio::config "networks[${network}].netmask")
- RANGE_END=$(bashio::config "networks[${network}].range_end")
- RANGE_START=$(bashio::config "networks[${network}].range_start")
- SUBNET=$(bashio::config "networks[${network}].subnet")
-
- {
- echo "subnet ${SUBNET} netmask ${NETMASK} {"
- echo " interface ${INTERFACE};"
- echo " range ${RANGE_START} ${RANGE_END};"
- echo " option routers ${GATEWAY};"
- echo " option broadcast-address ${BROADCAST};"
- echo "}"
- } >> "${CONFIG}"
-done
-
-# Create hosts
-for host in $(bashio::config 'hosts|keys'); do
- IP=$(bashio::config "hosts[${host}].ip")
- MAC=$(bashio::config "hosts[${host}].mac")
- NAME=$(bashio::config "hosts[${host}].name")
-
- {
- echo "host ${NAME} {"
- echo " hardware ethernet ${MAC};"
- echo " fixed-address ${IP};"
- echo " option host-name \"${NAME}\";"
- echo "}"
- } >> "${CONFIG}"
-done
-
-# Create database
-if ! bashio::fs.file_exists "${LEASES}"; then
- touch "${LEASES}"
-fi
-
-# Start DHCP server
-bashio::log.info "Starting DHCP server..."
-exec /usr/sbin/dhcpd \
- -4 -f -d --no-pid \
- -lf "${LEASES}" \
- -cf "${CONFIG}" \
- < /dev/null
diff --git a/dhcp_server/icon.png b/dhcp_server/icon.png
deleted file mode 100644
index b2d889511c0..00000000000
Binary files a/dhcp_server/icon.png and /dev/null differ
diff --git a/dhcp_server/logo.png b/dhcp_server/logo.png
deleted file mode 100644
index a481fe6c1da..00000000000
Binary files a/dhcp_server/logo.png and /dev/null differ
diff --git a/dhcp_server/translations/en.yaml b/dhcp_server/translations/en.yaml
deleted file mode 100644
index fa29373b8e3..00000000000
--- a/dhcp_server/translations/en.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
----
-configuration:
- default_lease:
- name: Default Lease Time
- description: >-
- The default time in seconds that the IP is leased to your client.
- dns:
- name: DNS Servers
- description: The DNS servers your DHCP server gives to your clients.
- domain:
- name: Domain
- description: >-
- Your network domain name, e.g., `mynetwork.local` or `home.local`
- hosts:
- name: Hosts
- description: >-
- This option defines settings for one or host definitions for the DHCP
- server.
- max_lease:
- name: Max Lease Time
- description: The max time in seconds that the IP is leased to your client.
- networks:
- name: Networks
- description: >-
- This option defines settings for one or multiple networks for the DHCP
- server to hand out IP addresses for.
diff --git a/dnsmasq/CHANGELOG.md b/dnsmasq/CHANGELOG.md
index 4d10d941603..61ddd24a7ba 100644
--- a/dnsmasq/CHANGELOG.md
+++ b/dnsmasq/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## 1.8.1
+
+- Fix config bug of cache_size option
+
+## 1.8.0
+
+- Add cache_size option
+
+## 1.7.0
+
+- Update to Alpine 3.19
+
## 1.6.0
- Update to Alpine 3.17
diff --git a/dnsmasq/DOCS.md b/dnsmasq/DOCS.md
index 3e4fc5a3b25..15dfa8a11f0 100644
--- a/dnsmasq/DOCS.md
+++ b/dnsmasq/DOCS.md
@@ -1,26 +1,26 @@
-# Home Assistant Add-on: Dnsmasq
+# Home Assistant App: Dnsmasq
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Dnsmasq" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Dnsmasq" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The add-on has a couple of options available. For more detailed instructions
-see below. The basic thing to get the add-on running would be:
+The app has a couple of options available. For more detailed instructions
+see below. The basic thing to get the app running would be:
-1. Start the add-on.
+1. Start the app.
## Configuration
-The Dnsmasq add-on can be tweaked to your likings. This section
-describes each of the add-on configuration options.
+The Dnsmasq app can be tweaked to your likings. This section
+describes each of the app configuration options.
-Example add-on configuration:
+Example app configuration:
```yaml
defaults:
@@ -123,6 +123,10 @@ The target name. Note that this only works for targets which are names from DHCP
Log all DNS requests. Defaults to `false`.
+### Option: `cache_size`
+
+Sets the size of the Dnsmasq cache. The default setting is 150. If this is set to 0 this disables caching. Note that huge cache sizes can create performance problems.
+
## Support
Got questions?
diff --git a/dnsmasq/README.md b/dnsmasq/README.md
index d5e0583f3a1..e95ab6d4d8d 100644
--- a/dnsmasq/README.md
+++ b/dnsmasq/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: Dnsmasq
+# Home Assistant App: Dnsmasq
A simple DNS server.
diff --git a/dnsmasq/build.yaml b/dnsmasq/build.yaml
index 896c0b943d2..19306375de0 100644
--- a/dnsmasq/build.yaml
+++ b/dnsmasq/build.yaml
@@ -1,10 +1,7 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.17
- amd64: ghcr.io/home-assistant/amd64-base:3.17
- armhf: ghcr.io/home-assistant/armhf-base:3.17
- armv7: ghcr.io/home-assistant/armv7-base:3.17
- i386: ghcr.io/home-assistant/i386-base:3.17
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.19
+ amd64: ghcr.io/home-assistant/amd64-base:3.19
+ armhf: ghcr.io/home-assistant/armhf-base:3.19
+ armv7: ghcr.io/home-assistant/armv7-base:3.19
+ i386: ghcr.io/home-assistant/i386-base:3.19
diff --git a/dnsmasq/config.yaml b/dnsmasq/config.yaml
index cdcd7dae2eb..45591570b7a 100644
--- a/dnsmasq/config.yaml
+++ b/dnsmasq/config.yaml
@@ -1,5 +1,5 @@
---
-version: 1.6.0
+version: 1.8.1
slug: dnsmasq
name: Dnsmasq
description: A simple DNS server
@@ -22,6 +22,7 @@ options:
services: []
cnames: []
log_queries: false
+ cache_size: 150
ports:
53/tcp: 53
53/udp: 53
@@ -44,4 +45,5 @@ schema:
- name: str
target: str
log_queries: bool
+ cache_size: int
startup: system
diff --git a/dnsmasq/rootfs/etc/cont-init.d/config.sh b/dnsmasq/rootfs/etc/cont-init.d/config.sh
index 24d3e00d2d6..e1b35e15b5a 100755
--- a/dnsmasq/rootfs/etc/cont-init.d/config.sh
+++ b/dnsmasq/rootfs/etc/cont-init.d/config.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# DNSMASQ config
# ==============================================================================
diff --git a/dnsmasq/rootfs/etc/services.d/dnsmasq/finish b/dnsmasq/rootfs/etc/services.d/dnsmasq/finish
index 5a23d05348c..f4c53b282d0 100755
--- a/dnsmasq/rootfs/etc/services.d/dnsmasq/finish
+++ b/dnsmasq/rootfs/etc/services.d/dnsmasq/finish
@@ -1,4 +1,5 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
diff --git a/dnsmasq/rootfs/etc/services.d/dnsmasq/run b/dnsmasq/rootfs/etc/services.d/dnsmasq/run
index 06224ffcc6a..62771823a80 100755
--- a/dnsmasq/rootfs/etc/services.d/dnsmasq/run
+++ b/dnsmasq/rootfs/etc/services.d/dnsmasq/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
CONFIG="/etc/dnsmasq.conf"
# Run dnsmasq
diff --git a/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config b/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config
index 3f8a8f27182..6068b47d066 100644
--- a/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config
+++ b/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config
@@ -9,6 +9,7 @@ log-queries
log-facility=-
no-poll
user=root
+cache-size={{ .cache_size}}
# Default forward servers
{{ range .defaults }}
diff --git a/duckdns/CHANGELOG.md b/duckdns/CHANGELOG.md
index 3a9824def54..8bdef5bd271 100644
--- a/duckdns/CHANGELOG.md
+++ b/duckdns/CHANGELOG.md
@@ -1,5 +1,50 @@
# Changelog
+## 1.26.0
+
+- Updated dehydrated fork with support for single-txt domains
+- Use the new dehydrated script parameters which handles individual domain processing now
+
+## 1.25.0
+
+- Wildcard support when using domains as "*.yourDomain.duckdns.org > yourDomain.duckdns.org"
+
+## 1.24.0
+
+- Add a pass to combine individual domains into a single certificate
+
+## 1.23.0
+
+- Improve GREP syntax for better stability for tokens with dashes
+
+## 1.22.0
+
+- Fix bashio logger issue
+
+## 1.21.0
+
+- Call Dehydrator per-domain or alias due to limitation in DuckDNS which can only handle a single TXT record at a time
+- Log the domain or alias being processed
+- Remove filtering of the domain = alias, otherwise, aliases are not getting renewed
+- Increase DuckDNS name server timeout to 120s
+
+## 1.20.0
+
+- Only deploy challenge for the main domain, aliases are handled through CNAME records
+
+## 1.19.0
+
+- Wait for up to 60 seconds for TXT record to propagate when deploying challenges
+
+## 1.18.0
+
+- Update to use s6-overlay to manage service
+- Update base image to Alpine 3.20
+
+## 1.17.0
+
+- Reduce log spam when updating IP address
+
## 1.16.0
- Update base image to Alpine 3.19
diff --git a/duckdns/DOCS.md b/duckdns/DOCS.md
index 029f013e728..6460ebe37ef 100644
--- a/duckdns/DOCS.md
+++ b/duckdns/DOCS.md
@@ -1,25 +1,25 @@
-# Home Assistant Add-on: DuckDNS
+# Home Assistant App: DuckDNS
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "DuckDNS" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "DuckDNS" app and click it.
3. Click on the "INSTALL" button.
## How to use
1. Visit [DuckDNS.org](https://www.duckdns.org/) and create an account by logging in through any of the available account services (Google, Github, Twitter, Persona, Reddit).
2. In the `Domains` section, type the name of the subdomain you wish to register and click `add domain`.
-3. If registration was a success, the subdomain is listed in the `Domains` section along with `current ip` being the public IP address of the device you are currently using to access `duckdns.org`. The IP address will be updated by the DuckDNS add-on.
-4. In the DuckDNS add-on configuration, perform the following:
+3. If registration was a success, the subdomain is listed in the `Domains` section along with `current ip` being the public IP address of the device you are currently using to access `duckdns.org`. The IP address will be updated by the DuckDNS app.
+4. In the DuckDNS app configuration, perform the following:
- Copy the DuckDNS token (listed at the top of the page where account details are displayed) from `duckdns.org` and paste into the `token` option.
- Update the `domains` option with the full domain name you registered. E.g., `my-domain.duckdns.org`.
## Configuration
-Add-on configuration:
+App configuration:
```yaml
lets_encrypt:
@@ -52,13 +52,13 @@ Once you have read and accepted the Let's Encrypt [Subscriber Agreement](https:/
#### Option `lets_encrypt.certfile`
-The name of the certificate file generated by Let's Encrypt. The file is used for SSL by Home Assistant add-ons and is recommended to keep the filename as-is (`fullchain.pem`) for compatibility.
+The name of the certificate file generated by Let's Encrypt. The file is used for SSL by Home Assistant apps and is recommended to keep the filename as-is (`fullchain.pem`) for compatibility.
**Note**: _The file is stored in `/ssl/`, which is the default for Home Assistant_
#### Option `lets_encrypt.keyfile`
-The name of the private key file generated by Let's Encrypt. The private key file is used for SSL by Home Assistant add-ons and is recommended to keep the filename as-is (`privkey.pem`) for compatibility.
+The name of the private key file generated by Let's Encrypt. The private key file is used for SSL by Home Assistant apps and is recommended to keep the filename as-is (`privkey.pem`) for compatibility.
**Note**: _The file is stored in `/ssl/`, which is the default for Home Assistant_
@@ -98,12 +98,14 @@ The DuckDNS authentication token found at the top of the DuckDNS account landing
### Option: `domains`
A list of DuckDNS subdomains registered under your account. An acceptable naming convention is `my-domain.duckdns.org`.
+Wildcard certificates can also be issued by using the syntax `*.my-domain.duckdns.org > my-domain.duckdns.org`.
### Option: `aliases` (optional)
A list aliases of domains configured on the `domains` option.
This is useful in cases where you would like to use your own domain.
Create a CNAME record to point at the DuckDNS subdomain and set this value accordingly.
+It is recommended to set the TTL value on your CNAME to a low value, typically under 60.
For example:
diff --git a/duckdns/Dockerfile b/duckdns/Dockerfile
index a639c87d0e8..0ebd61ceaff 100644
--- a/duckdns/Dockerfile
+++ b/duckdns/Dockerfile
@@ -5,10 +5,8 @@ FROM $BUILD_FROM
ARG DEHYDRATED_VERSION
RUN apk add --no-cache openssl \
&& curl -s -o /usr/bin/dehydrated \
- "https://raw.githubusercontent.com/lukas2511/dehydrated/v${DEHYDRATED_VERSION}/dehydrated" \
+ "https://raw.githubusercontent.com/Xebozone/dehydrated/${DEHYDRATED_VERSION}/dehydrated" \
&& chmod a+x /usr/bin/dehydrated
-# Copy data
-COPY data/*.sh /
-
-CMD [ "/run.sh" ]
+# Copy root filesystem
+COPY rootfs /
diff --git a/duckdns/README.md b/duckdns/README.md
index 94b7243ef4d..ac0efc1e7b4 100644
--- a/duckdns/README.md
+++ b/duckdns/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: DuckDNS
+# Home Assistant App: DuckDNS
Automatically update your Duck DNS IP address with integrated HTTPS support via Let's Encrypt.
@@ -6,7 +6,7 @@ Automatically update your Duck DNS IP address with integrated HTTPS support via
## About
-[Duck DNS][duckdns] is a free service that points a DNS (sub-domains of duckdns.org) to an IP of your choice. This add-on includes support for Let’s Encrypt and automatically creates and renews your certificates. You need to sign up for a Duck DNS account before using this add-on.
+[Duck DNS][duckdns] is a free service that points a DNS (sub-domains of duckdns.org) to an IP of your choice. This app (formerly known as add-on) includes support for Let’s Encrypt and automatically creates and renews your certificates. You need to sign up for a Duck DNS account before using this app.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
diff --git a/duckdns/build.yaml b/duckdns/build.yaml
index 592be6424a2..6243e988e5d 100644
--- a/duckdns/build.yaml
+++ b/duckdns/build.yaml
@@ -1,12 +1,9 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armhf: ghcr.io/home-assistant/armhf-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.20
+ amd64: ghcr.io/home-assistant/amd64-base:3.20
+ armhf: ghcr.io/home-assistant/armhf-base:3.20
+ armv7: ghcr.io/home-assistant/armv7-base:3.20
+ i386: ghcr.io/home-assistant/i386-base:3.20
args:
- DEHYDRATED_VERSION: 0.7.1
+ DEHYDRATED_VERSION: 0.8.0
diff --git a/duckdns/config.yaml b/duckdns/config.yaml
index 230a560097c..3c066dae752 100644
--- a/duckdns/config.yaml
+++ b/duckdns/config.yaml
@@ -1,5 +1,5 @@
---
-version: 1.16.0
+version: 1.26.0
slug: duckdns
name: Duck DNS
description: >-
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/mdns b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/dependencies.d/base
similarity index 100%
rename from openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/mdns
rename to duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/dependencies.d/base
diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish
new file mode 100755
index 00000000000..57efe3f4f85
--- /dev/null
+++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish
@@ -0,0 +1,28 @@
+#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# Home Assistant Community Add-on: chrony
+# Take down the S6 supervision tree when chrony 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
\ No newline at end of file
diff --git a/duckdns/data/run.sh b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run
similarity index 61%
rename from duckdns/data/run.sh
rename to duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run
index 68a5c3cb266..23c2b1ff19a 100755
--- a/duckdns/data/run.sh
+++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
CERT_DIR=/data/letsencrypt
WORK_DIR=/data/workdir
@@ -18,26 +20,40 @@ ALGO=$(bashio::config 'lets_encrypt.algo')
function le_renew() {
local domain_args=()
local domains=''
- local aliases=''
+ local aliases=()
+ local domainsAndAliases=()
domains=$(bashio::config 'domains')
# Prepare domain for Let's Encrypt
+
+ # Get a list of aliases against domains first from the options file
for domain in ${domains}; do
for alias in $(jq --raw-output --exit-status "[.aliases[]|{(.alias):.domain}]|add.\"${domain}\" | select(. != null)" /data/options.json) ; do
- aliases="${aliases} ${alias}"
+ aliases+=("${alias}")
done
done
- aliases="$(echo "${aliases}" | tr ' ' '\n' | sort | uniq)"
-
- bashio::log.info "Renew certificate for domains: $(echo -n "${domains}") and aliases: $(echo -n "${aliases}")"
-
- for domain in $(echo "${domains}" "${aliases}" | tr ' ' '\n' | sort | uniq); do
- domain_args+=("--domain" "${domain}")
+ readarray -t domainsarray <<< "$domains" # line-separated list of domains into an array
+ bashio::log.info "Renew certificate for domains: $(echo -n "${domainsarray[@]}") and aliases: $(echo -n "${aliases[@]}")"
+
+ # Combine domains and aliases into one array, skipping duplicates
+ declare -A seen
+ for element in "${domainsarray[@]}" "${aliases[@]}"; do
+ if [[ -n "${element}" && -z "${seen["$element"]+x}" ]]; then
+ seen["$element"]=1
+ domainsAndAliases+=("${element}")
+ fi
+ done
+
+ # Prepare arguments
+ for domain in "${domainsAndAliases[@]}"; do
+ domain_args+=("--domain" "${domain}")
done
+
+ # Do the certificate renewals
+ dehydrated --cron --separate-challenges --algo "${ALGO}" --hook /root/hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config" || true
- dehydrated --cron --algo "${ALGO}" --hook ./hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config" || true
LE_UPDATE="$(date +%s)"
}
@@ -63,8 +79,8 @@ if bashio::config.true 'lets_encrypt.accept_terms'; then
fi
# Run duckdns
+bashio::log.info "Starting DuckDNS..."
while true; do
-
[[ ${IPV4} != *:/* ]] && ipv4=${IPV4} || ipv4=$(curl -s -m 10 "${IPV4}")
[[ ${IPV6} != *:/* ]] && ipv6=${IPV6} || ipv6=$(curl -s -m 10 "${IPV6}")
@@ -80,18 +96,29 @@ while true; do
fi
done
fi
+
+ # Sanitise the DOMAINS, filtering out duplicates, subdomains and wildcard aliases and retaining just the instances of my-domain.duckdns.org
+ duckdnsDomains=$(echo "$DOMAINS" | grep -Eo '[^ .>,]+\.duckdns\.org' | sort -u | paste -sd,)
if [[ ${ipv6} == *:* ]]; then
- if answer="$(curl -s "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}&ipv6=${ipv6}&verbose=true")" && [ "${answer}" != 'KO' ]; then
- bashio::log.info "${answer}"
+ if answer="$(curl -s "https://www.duckdns.org/update?domains=${duckdnsDomains}&token=${TOKEN}&ipv6=${ipv6}&verbose=true")" && [ "${answer}" != 'KO' ]; then
+ if [[ "${answer}" == *NOCHANGE* ]]; then
+ bashio::log.debug "${answer}"
+ else
+ bashio::log.info "${answer}"
+ fi
else
bashio::log.warning "${answer}"
fi
fi
if [[ -z ${ipv4} || ${ipv4} == *.* ]]; then
- if answer="$(curl -s "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}&ip=${ipv4}&verbose=true")" && [ "${answer}" != 'KO' ]; then
- bashio::log.info "${answer}"
+ if answer="$(curl -s "https://www.duckdns.org/update?domains=${duckdnsDomains}&token=${TOKEN}&ip=${ipv4}&verbose=true")" && [ "${answer}" != 'KO' ]; then
+ if [[ "${answer}" == *NOCHANGE* ]]; then
+ bashio::log.debug "${answer}"
+ else
+ bashio::log.info "${answer}"
+ fi
else
bashio::log.warning "${answer}"
fi
diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type
new file mode 100644
index 00000000000..1780f9f44ef
--- /dev/null
+++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/universal-silabs-flasher b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/duckdns
similarity index 100%
rename from openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/universal-silabs-flasher
rename to duckdns/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/duckdns
diff --git a/duckdns/data/hooks.sh b/duckdns/rootfs/root/hooks.sh
similarity index 88%
rename from duckdns/data/hooks.sh
rename to duckdns/rootfs/root/hooks.sh
index b3f9bc90a24..16a9297b1e6 100755
--- a/duckdns/data/hooks.sh
+++ b/duckdns/rootfs/root/hooks.sh
@@ -14,6 +14,9 @@ deploy_challenge() {
local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}" ALIAS
ALIAS="$(jq --raw-output --exit-status "[.aliases[]|{(.domain):.alias}]|add.\"$DOMAIN\"" $CONFIG_PATH)" || ALIAS="$DOMAIN"
+ echo "Processing domain: $DOMAIN"
+ echo ""
+
# This hook is called once for every domain that needs to be
# validated, including any alternative names you may have listed.
#
@@ -31,7 +34,12 @@ deploy_challenge() {
# TXT record. For HTTP validation it is the value that is expected
# be found in the $TOKEN_FILENAME file.
- curl -s "https://www.duckdns.org/update?domains=$ALIAS&token=$SYS_TOKEN&txt=$TOKEN_VALUE"
+ curl -s "https://www.duckdns.org/update?domains=$ALIAS&token=$SYS_TOKEN&txt=$TOKEN_VALUE"
+ timeout 120s bash -c -- "
+ while ! dig -t txt \"_acme-challenge.$ALIAS\" | grep -F -- \"$TOKEN_VALUE\" > /dev/null; do
+ sleep 5;
+ done
+ "
}
clean_challenge() {
@@ -44,7 +52,7 @@ clean_challenge() {
#
# The parameters are the same as for deploy_challenge.
- curl -s "https://www.duckdns.org/update?domains=$ALIAS&token=$SYS_TOKEN&txt=removed&clear=true"
+ curl -s "https://www.duckdns.org/update?domains=$ALIAS&token=$SYS_TOKEN&txt=removed&clear=true"
}
deploy_cert() {
diff --git a/git_pull/CHANGELOG.md b/git_pull/CHANGELOG.md
index 926de349bee..7a6034c8734 100644
--- a/git_pull/CHANGELOG.md
+++ b/git_pull/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## 8.0.1
+- Fix bashio warn(ing) logger usage breaking deployment keys
+
+## 8.0.0
+- Refactor git_pull to use HA Api with bashio
+- Update base image to Alpine 3.21
+- Remove ha cli dependency
+
+
+## 7.14.1
+- Fix error where $HOME is not defined
+
## 7.14.0
- Update base image to Alpine 3.19
diff --git a/git_pull/DOCS.md b/git_pull/DOCS.md
index 4e11e6c3a66..8541c3e4818 100644
--- a/git_pull/DOCS.md
+++ b/git_pull/DOCS.md
@@ -1,16 +1,16 @@
-# Home Assistant Add-on: Git pull
+# Home Assistant App: Git pull
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Git pull" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Git pull" app and click it.
3. Click on the "INSTALL" button.
## WARNING
-The risk of complete loss is possible. Prior to starting this add-on, ensure a copy
+The risk of complete loss is possible. Prior to starting this app, ensure a copy
of your Home Assistant configuration files exists in the Github repository. Otherwise,
your local machine configuration folder will be overwritten with an empty configuration
folder and you will need to restore from a backup.
@@ -21,22 +21,22 @@ In the configuration section, set the repository field to your repository's
clone URL and check if any other fields need to be customized to work with
your repository. Next,
-1. Start the add-on.
-2. Check the add-on log output to see the result.
+1. Start the app.
+2. Check the app log output to see the result.
-If the log doesn't end with an error, the add-on has successfully
+If the log doesn't end with an error, the app has successfully
accessed your git repository. Examples of logs you might see if
there were no errors are: `[Info] Nothing has changed.`,
`[Info] Something has changed, checking Home-Assistant config...`,
or `[Info] Local configuration has changed. Restart required.`.
-If you made it this far, you might want to let the add-on automatically
+If you made it this far, you might want to let the app automatically
check for updates by setting the `active` field (a subfield of `repeat`)
to `true` and turning on "Start on boot."
## Configuration
-Add-on configuration:
+App configuration:
```yaml
git_branch: master
@@ -71,7 +71,7 @@ Name of the tracked repository. Leave this as `origin` if you are unsure.
### Option: `git_prune` (required)
-`true`/`false`: If set to true, the add-on will clean-up branches that are deleted on the remote repository, but still have cached entries on the local machine. Leave this as `false` if you are unsure.
+`true`/`false`: If set to true, the app will clean-up branches that are deleted on the remote repository, but still have cached entries on the local machine. Leave this as `false` if you are unsure.
### Option: `git_branch` (required)
@@ -103,7 +103,7 @@ When `auto_restart` is enabled, changes to these files will not make HA restart.
### Option group: `repeat`
-The following options are for the option group: `repeat` and configure the Git pull add-on to poll the repository for updates periodically automatically.
+The following options are for the option group: `repeat` and configure the Git pull app to poll the repository for updates periodically automatically.
#### Option: `repeat.active` (required)
diff --git a/git_pull/Dockerfile b/git_pull/Dockerfile
index 732139a5d11..f4d9a5c70b3 100644
--- a/git_pull/Dockerfile
+++ b/git_pull/Dockerfile
@@ -4,13 +4,6 @@ FROM $BUILD_FROM
# Setup base
RUN apk add --no-cache jq curl git openssh-client
-# Home Assistant CLI
-ARG BUILD_ARCH
-ARG CLI_VERSION
-RUN curl -Lso /usr/bin/ha \
- "https://github.com/home-assistant/cli/releases/download/${CLI_VERSION}/ha_${BUILD_ARCH}" \
- && chmod a+x /usr/bin/ha
-
# Copy data
COPY data/run.sh /
diff --git a/git_pull/README.md b/git_pull/README.md
index bb1e8c8b5a1..543705bd964 100644
--- a/git_pull/README.md
+++ b/git_pull/README.md
@@ -1,10 +1,10 @@
-# Home Assistant Add-on: Git pull
+# Home Assistant App: Git pull
Load and update configuration files for Home Assistant from a Git repository.
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-You can use this add-on to `git pull` updates to your Home Assistant configuration files from a Git
+You can use this app (formerly known as add-on) to `git pull` updates to your Home Assistant configuration files from a Git
repository.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/git_pull/build.yaml b/git_pull/build.yaml
index 6aaa1c32cc5..a9a234c27c1 100644
--- a/git_pull/build.yaml
+++ b/git_pull/build.yaml
@@ -1,12 +1,7 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armhf: ghcr.io/home-assistant/armhf-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
-args:
- CLI_VERSION: 4.31.0
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.21
+ amd64: ghcr.io/home-assistant/amd64-base:3.21
+ armhf: ghcr.io/home-assistant/armhf-base:3.21
+ armv7: ghcr.io/home-assistant/armv7-base:3.21
+ i386: ghcr.io/home-assistant/i386-base:3.21
diff --git a/git_pull/config.yaml b/git_pull/config.yaml
index e6e90270453..1fd689f2161 100644
--- a/git_pull/config.yaml
+++ b/git_pull/config.yaml
@@ -1,5 +1,5 @@
---
-version: 7.14.0
+version: 8.0.1
slug: git_pull
name: Git pull
description: Simple git pull to update the local configuration
diff --git a/git_pull/data/run.sh b/git_pull/data/run.sh
index 001a5ac91e0..0f5cae42abb 100755
--- a/git_pull/data/run.sh
+++ b/git_pull/data/run.sh
@@ -1,27 +1,29 @@
-#!/bin/bash
-
-#### config ####
+#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# shellcheck disable=SC2034
CONFIG_PATH=/data/options.json
-
-DEPLOYMENT_KEY=$(jq --raw-output ".deployment_key[]" $CONFIG_PATH)
-DEPLOYMENT_KEY_PROTOCOL=$(jq --raw-output ".deployment_key_protocol" $CONFIG_PATH)
-DEPLOYMENT_USER=$(jq --raw-output ".deployment_user" $CONFIG_PATH)
-DEPLOYMENT_PASSWORD=$(jq --raw-output ".deployment_password" $CONFIG_PATH)
-GIT_BRANCH=$(jq --raw-output '.git_branch' $CONFIG_PATH)
-GIT_COMMAND=$(jq --raw-output '.git_command' $CONFIG_PATH)
-GIT_REMOTE=$(jq --raw-output '.git_remote' $CONFIG_PATH)
-GIT_PRUNE=$(jq --raw-output '.git_prune' $CONFIG_PATH)
-REPOSITORY=$(jq --raw-output '.repository' $CONFIG_PATH)
-AUTO_RESTART=$(jq --raw-output '.auto_restart' $CONFIG_PATH)
-RESTART_IGNORED_FILES=$(jq --raw-output '.restart_ignore | join(" ")' $CONFIG_PATH)
-REPEAT_ACTIVE=$(jq --raw-output '.repeat.active' $CONFIG_PATH)
-REPEAT_INTERVAL=$(jq --raw-output '.repeat.interval' $CONFIG_PATH)
+HOME=~
+
+DEPLOYMENT_KEY=$(bashio::config 'deployment_key')
+DEPLOYMENT_KEY_PROTOCOL=$(bashio::config 'deployment_key_protocol')
+DEPLOYMENT_USER=$(bashio::config 'deployment_user')
+DEPLOYMENT_PASSWORD=$(bashio::config 'deployment_password')
+GIT_BRANCH=$(bashio::config 'git_branch')
+GIT_COMMAND=$(bashio::config 'git_command')
+GIT_REMOTE=$(bashio::config 'git_remote')
+GIT_PRUNE=$(bashio::config 'git_prune')
+REPOSITORY=$(bashio::config 'repository')
+AUTO_RESTART=$(bashio::config 'auto_restart')
+RESTART_IGNORED_FILES=$(bashio::config 'restart_ignore | join(" ")')
+REPEAT_ACTIVE=$(bashio::config 'repeat.active')
+REPEAT_INTERVAL=$(bashio::config 'repeat.interval')
################
#### functions ####
function add-ssh-key {
- echo "[Info] Start adding SSH key"
+ bashio::log.info "[Info] Start adding SSH key"
mkdir -p ~/.ssh
(
@@ -29,7 +31,7 @@ function add-ssh-key {
echo " StrictHostKeyChecking no"
) > ~/.ssh/config
- echo "[Info] Setup deployment_key on id_${DEPLOYMENT_KEY_PROTOCOL}"
+ bashio::log.info "[Info] Setup deployment_key on id_${DEPLOYMENT_KEY_PROTOCOL}"
rm -f "${HOME}/.ssh/id_${DEPLOYMENT_KEY_PROTOCOL}"
while read -r line; do
echo "$line" >> "${HOME}/.ssh/id_${DEPLOYMENT_KEY_PROTOCOL}"
@@ -42,17 +44,17 @@ function add-ssh-key {
function git-clone {
# create backup
BACKUP_LOCATION="/tmp/config-$(date +%Y-%m-%d_%H-%M-%S)"
- echo "[Info] Backup configuration to $BACKUP_LOCATION"
+ bashio::log.info "[Info] Backup configuration to $BACKUP_LOCATION"
- mkdir "${BACKUP_LOCATION}" || { echo "[Error] Creation of backup directory failed"; exit 1; }
- cp -rf /config/* "${BACKUP_LOCATION}" || { echo "[Error] Copy files to backup directory failed"; exit 1; }
+ mkdir "${BACKUP_LOCATION}" || bashio::exit.nok "[Error] Creation of backup directory failed"
+ cp -rf /config/* "${BACKUP_LOCATION}" || bashio::exit.nok "[Error] Copy files to backup directory failed"
# remove config folder content
- rm -rf /config/{,.[!.],..?}* || { echo "[Error] Clearing /config failed"; exit 1; }
+ rm -rf /config/{,.[!.],..?}* || bashio::exit.nok "[Error] Clearing /config failed"
# git clone
- echo "[Info] Start git clone"
- git clone "$REPOSITORY" /config || { echo "[Error] Git clone failed"; exit 1; }
+ bashio::log.info "[Info] Start git clone"
+ git clone "$REPOSITORY" /config || bashio::exit.nok "[Error] Git clone failed"
# try to copy non yml files back
cp "${BACKUP_LOCATION}" "!(*.yaml)" /config 2>/dev/null
@@ -63,14 +65,14 @@ function git-clone {
function check-ssh-key {
if [ -n "$DEPLOYMENT_KEY" ]; then
- echo "Check SSH connection"
+ bashio::log.info "Check SSH connection"
IFS=':' read -ra GIT_URL_PARTS <<< "$REPOSITORY"
# shellcheck disable=SC2029
DOMAIN="${GIT_URL_PARTS[0]}"
if OUTPUT_CHECK=$(ssh -T -o "StrictHostKeyChecking=no" -o "BatchMode=yes" "$DOMAIN" 2>&1) || { [[ $DOMAIN = *"@github.com"* ]] && [[ $OUTPUT_CHECK = *"You've successfully authenticated"* ]]; }; then
- echo "[Info] Valid SSH connection for $DOMAIN"
+ bashio::log.info "[Info] Valid SSH connection for $DOMAIN"
else
- echo "[Warn] No valid SSH connection for $DOMAIN"
+ bashio::log.warning "[Warn] No valid SSH connection for $DOMAIN"
add-ssh-key
fi
fi
@@ -79,7 +81,7 @@ fi
function setup-user-password {
if [ -n "$DEPLOYMENT_USER" ]; then
cd /config || return
- echo "[Info] setting up credential.helper for user: ${DEPLOYMENT_USER}"
+ bashio::log.info "[Info] setting up credential.helper for user: ${DEPLOYMENT_USER}"
git config --system credential.helper 'store --file=/tmp/git-credentials'
# Extract the hostname from repository
@@ -107,7 +109,7 @@ password=${DEPLOYMENT_PASSWORD}
"
# Use git commands to write the credentials to ~/.git-credentials
- echo "[Info] Saving git credentials to /tmp/git-credentials"
+ bashio::log.info "[Info] Saving git credentials to /tmp/git-credentials"
# shellcheck disable=SC2259
git credential fill | git credential approve <<< "$cred_data"
fi
@@ -115,116 +117,121 @@ fi
function git-synchronize {
# is /config a local git repo?
- if git rev-parse --is-inside-work-tree &>/dev/null
- then
- echo "[Info] Local git repository exists"
-
- # Is the local repo set to the correct origin?
- CURRENTGITREMOTEURL=$(git remote get-url --all "$GIT_REMOTE" | head -n 1)
- if [ "$CURRENTGITREMOTEURL" = "$REPOSITORY" ]
- then
- echo "[Info] Git origin is correctly set to $REPOSITORY"
- OLD_COMMIT=$(git rev-parse HEAD)
-
- # Always do a fetch to update repos
- echo "[Info] Start git fetch..."
- git fetch "$GIT_REMOTE" || { echo "[Error] Git fetch failed"; return 1; }
-
- # Prune if configured
- if [ "$GIT_PRUNE" == "true" ]
- then
- echo "[Info] Start git prune..."
- git prune || { echo "[Error] Git prune failed"; return 1; }
- fi
+ if ! git rev-parse --is-inside-work-tree &>/dev/null; then
+ bashio::log.warning "[Warn] Git repository doesn't exist"
+ git-clone
+ return
+ fi
- # Do we switch branches?
- GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)
- if [ -z "$GIT_BRANCH" ] || [ "$GIT_BRANCH" == "$GIT_CURRENT_BRANCH" ]; then
- echo "[Info] Staying on currently checked out branch: $GIT_CURRENT_BRANCH..."
- else
- echo "[Info] Switching branches - start git checkout of branch $GIT_BRANCH..."
- git checkout "$GIT_BRANCH" || { echo "[Error] Git checkout failed"; exit 1; }
- GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)
- fi
+ bashio::log.info "[Info] Local git repository exists"
+ # Is the local repo set to the correct origin?
+ CURRENTGITREMOTEURL=$(git remote get-url --all "$GIT_REMOTE" | head -n 1)
+ if [ "$CURRENTGITREMOTEURL" != "$REPOSITORY" ]; then
+ bashio::exit.nok "[Error] git origin does not match $REPOSITORY!";
+ return
+ fi
- # Pull or reset depending on user preference
- case "$GIT_COMMAND" in
- pull)
- echo "[Info] Start git pull..."
- git pull || { echo "[Error] Git pull failed"; return 1; }
- ;;
- reset)
- echo "[Info] Start git reset..."
- git reset --hard "$GIT_REMOTE"/"$GIT_CURRENT_BRANCH" || { echo "[Error] Git reset failed"; return 1; }
- ;;
- *)
- echo "[Error] Git command is not set correctly. Should be either 'reset' or 'pull'"
- exit 1
- ;;
- esac
- else
- echo "[Error] git origin does not match $REPOSITORY!"; exit 1;
- fi
+ bashio::log.info "[Info] Git origin is correctly set to $REPOSITORY"
+ OLD_COMMIT=$(git rev-parse HEAD)
+ # Always do a fetch to update repos
+ bashio::log.info "[Info] Start git fetch..."
+ git fetch "$GIT_REMOTE" "$GIT_BRANCH" || bashio::exit.nok "[Error] Git fetch failed";
+
+ # Prune if configured
+ if [ "$GIT_PRUNE" == "true" ]
+ then
+ bashio::log.info "[Info] Start git prune..."
+ git prune || bashio::exit.nok "[Error] Git prune failed";
+ fi
+
+ # Do we switch branches?
+ GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)
+ if [ -z "$GIT_BRANCH" ] || [ "$GIT_BRANCH" == "$GIT_CURRENT_BRANCH" ]; then
+ bashio::log.info "[Info] Staying on currently checked out branch: $GIT_CURRENT_BRANCH..."
else
- echo "[Warn] Git repository doesn't exist"
- git-clone
+ bashio::log.info "[Info] Switching branches - start git checkout of branch $GIT_BRANCH..."
+ git checkout "$GIT_BRANCH" || bashio::exit.nok "[Error] Git checkout failed"
+ GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)
fi
+
+ # Pull or reset depending on user preference
+ case "$GIT_COMMAND" in
+ pull)
+ bashio::log.info "[Info] Start git pull..."
+ git pull || bashio::exit.nok "[Error] Git pull failed";
+ ;;
+ reset)
+ bashio::log.info "[Info] Start git reset..."
+ git reset --hard "$GIT_REMOTE"/"$GIT_CURRENT_BRANCH" || bashio::exit.nok "[Error] Git reset failed";
+ ;;
+ *)
+ bashio::exit.nok "[Error] Git command is not set correctly. Should be either 'reset' or 'pull'"
+ ;;
+ esac
}
function validate-config {
- echo "[Info] Checking if something has changed..."
+ bashio::log.info "[Info] Checking if something has changed..."
# Compare commit ids & check config
NEW_COMMIT=$(git rev-parse HEAD)
- if [ "$NEW_COMMIT" != "$OLD_COMMIT" ]; then
- echo "[Info] Something has changed, checking Home-Assistant config..."
- if ha --no-progress core check; then
- if [ "$AUTO_RESTART" == "true" ]; then
- DO_RESTART="false"
- CHANGED_FILES=$(git diff "$OLD_COMMIT" "$NEW_COMMIT" --name-only)
- echo "Changed Files: $CHANGED_FILES"
- if [ -n "$RESTART_IGNORED_FILES" ]; then
- for changed_file in $CHANGED_FILES; do
- restart_required_file=""
- for restart_ignored_file in $RESTART_IGNORED_FILES; do
- if [ -d "$restart_ignored_file" ]; then
- # file to be ignored is a whole dir
- restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}")
- else
- restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}$")
- fi
- # break on first match
- if [ -n "$restart_required_file" ]; then break; fi
- done
- if [ -z "$restart_required_file" ]; then
- DO_RESTART="true"
- echo "[Info] Detected restart-required file: $changed_file"
- fi
- done
- else
- DO_RESTART="true"
- fi
- if [ "$DO_RESTART" == "true" ]; then
- echo "[Info] Restart Home-Assistant"
- ha --no-progress core restart 2&> /dev/null
+ if [ "$NEW_COMMIT" == "$OLD_COMMIT" ]; then
+ bashio::log.info "[Info] Nothing has changed."
+ return
+ fi
+ bashio::log.info "[Info] Something has changed, checking Home-Assistant config..."
+ if ! bashio::core.check; then
+ bashio::log.error "[Error] Configuration updated but it does not pass the config check. Do not restart until this is fixed!"
+ return
+ fi
+ if [ "$AUTO_RESTART" != "true" ]; then
+ bashio::log.info "[Info] Local configuration has changed. Restart required."
+ return
+ fi
+ DO_RESTART="false"
+ CHANGED_FILES=$(git diff "$OLD_COMMIT" "$NEW_COMMIT" --name-only)
+ bashio::log.info "Changed Files: $CHANGED_FILES"
+ if [ -n "$RESTART_IGNORED_FILES" ]; then
+ for changed_file in $CHANGED_FILES; do
+ restart_required_file=""
+ for restart_ignored_file in $RESTART_IGNORED_FILES; do
+ bashio::log.info "[Info] Checking: $changed_file for $restart_ignored_file"
+ if [ -d "$restart_ignored_file" ]; then
+ # file to be ignored is a whole dir
+ set +e
+ restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}")
+ set -e
else
- echo "[Info] No Restart Required, only ignored changes detected"
+ set +e
+ restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}$")
+ set -e
fi
+ # break on first match
+ if [ -n "$restart_required_file" ]; then break; fi
+ done
+ if [ -z "$restart_required_file" ]; then
+ DO_RESTART="true"
+ bashio::log.info "[Info] Detected restart-required file: $changed_file"
else
- echo "[Info] Local configuration has changed. Restart required."
+ bashio::log.info "[Info] Detected ignored file: $changed_file"
fi
- else
- echo "[Error] Configuration updated but it does not pass the config check. Do not restart until this is fixed!"
- fi
+ done
+ else
+ DO_RESTART="true"
+ fi
+
+ if [ "$DO_RESTART" == "true" ]; then
+ bashio::log.info "[Info] Restart Home-Assistant"
+ bashio::core.restart
else
- echo "[Info] Nothing has changed."
+ bashio::log.info "[Info] No Restart Required, only ignored changes detected"
fi
}
###################
#### Main program ####
-cd /config || { echo "[Error] Failed to cd into /config"; exit 1; }
+cd /config || bashio::exit.nok "[Error] Failed to cd into /config";
while true; do
check-ssh-key
diff --git a/git_pull/translations/en.yaml b/git_pull/translations/en.yaml
index f7e687cc2c2..b4335f6939b 100644
--- a/git_pull/translations/en.yaml
+++ b/git_pull/translations/en.yaml
@@ -27,7 +27,7 @@ configuration:
git_prune:
name: Git Prune
description: >-
- If enabled, the add-on will clean-up branches that are deleted on the
+ If enabled, the app will clean-up branches that are deleted on the
remote repository, but still have cached entries on the local machine.
Leave this as `false` if you are unsure.
deployment_key:
@@ -51,5 +51,5 @@ configuration:
repeat:
name: Polling
description: >-
- Configure the Git pull add-on to poll the repository for updates
+ Configure the Git pull app to poll the repository for updates
periodically automatically.
diff --git a/google_assistant/CHANGELOG.md b/google_assistant/CHANGELOG.md
deleted file mode 100644
index d6e260b0d98..00000000000
--- a/google_assistant/CHANGELOG.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Changelog
-
-## 2.5.0
-
-- Add an option to enable feedback sounds
-
-## 2.4.0
-
-- Improve OAuth connection process UI
-- Fix error 500 after submitting the OAuth token
-
-## 2.3.2
-
-- Update Google Assistant SDK back to 0.5.1
-- Update Google Assistant Library back to 1.0.0
-
-## 2.3.1
-
-- Fix build armv7/armhf
-- Spell error break startup
-
-## 2.3.0
-
-- Update Google Assistant SDK 0.5.1
-- Update Google Assistant Library 1.1.0
-- Use homeassistant debian base images
-- Support new audio backend
-- Migrate to s6-overlay
-
-## 2.2.0
-
-- Use homeassistant ubuntu base images
-
-## 2.1.0
-
-- Add error handling for decoding UTF-8
-
-## 2.0.0
-
-- Update Google Assistant SDK 0.5.0
-- Update Google Assistant Library 1.0.0
-- Revert base images
diff --git a/google_assistant/DOCS.md b/google_assistant/DOCS.md
deleted file mode 100644
index 858da0777ef..00000000000
--- a/google_assistant/DOCS.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# Home Assistant Add-on: Google Assistant SDK
-
-## Installation
-
-Follow these steps to get the add-on installed on your system:
-
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Google Assistant SDK" add-on and click it.
-3. Click on the "INSTALL" button.
-
-## Configuration
-
-Add-on configuration:
-
-```yaml
-client_secrets: google_assistant.json
-project_id: project_id_from_google
-model_id: model_id_from_google
-```
-
-### Option: `clients_secrets` (required)
-
-The name of the client secrets file to you've downloaded from Google and placed in your `/share` folder.
-
-### Option: `project_id` (required)
-
-Project ID of the project you've created at Google for this add-on.
-The project id can be found in your `google_assistant.json` file, or under project settings in the [Google Actions Console][google-actions-console].
-
-### Option: `model_id` (required)
-
-The ID of the model you've registered at Google for this add-on.
-
-The model id can also be found under the "Develop - Device registration" tab in the [Google Actions Console][google-actions-console].
-
-### Option group: `feedback`
-
-The following options are for the option group: `feedback`.
-
-#### Option: `feedback.enabled`
-
-Set to `true` if you want to hear feedback sounds when Google Assistant starts and stops listening to your command.
-
-#### Option: `feedback.volume`
-
-The percentage of volume to use for feedback sounds.
-
-## How to use
-
-You first need to enable access to the Google Assistant API.
-To do so, do the following:
-
-1. Go to the [Google Actions Console][google-actions-console] and create a new project.
-1. After you created the project on the bottom of the page click on "**Device registration**". Keep this tab open for later use.
-1. Enable the Google Assistant API on the new project through [this][google-assistant-api] link. Make sure you have the right project selected (shown in the middle of the screen in the top bar). If you can't select the right project, it may help to open the link in an incognito window.
-1. Configure the [OAuth consent screen][google-oauth-concent]. Again, check that you have the right project.
- 1. Choose "**External**" as the User Type.
- 1. Fill in a project name and your e-mail.
- 1. Hit "**Save**" at the bottom of the page.
-1. Go back to your device registration tab and click on "**REGISTER MODEL**". If you closed the tab, you can also open your project in the [Google Actions Console][google-actions-console], start the Quick setup, and in the left bar click "**Device registration**".
- 1. Give you project a name and think of a nice manufacturer. Select "**speaker**" for the device type. If you want to, edit your model id, and copy it for later use.
- 1. Click "**REGISTER MODEL**", and download the credentials.
- 1. Click "**Next**" and click "**SKIP**".
-1. Upload your credentials as `google_assistant.json` to the "hassio/share" folder, for example by using the [Samba][samba-addon] add-on.
-1. On the add-on Configuration tab:
- 1. In the "Config" section, fill-in you `project_id` and your `model_id` and hit "**Save**". Your project id can be found in the Google Actions console by clicking on the top right menu button and selecting "**Project settings**". This id may differ from the project name that you choose!
- 1. In the "Audio" section, select the input and output audio devices to use for the Assistant and hit "**Save**". On a Raspberry Pi 3, `ALSA device 0` is the built-in headset port and `ALSA device 1` is the HDMI port.
-1. The final step is to authenticate your Google account with Google Assistant.
- 1. Start the add-on. Check the log and click refresh till it says: `ENGINE Bus STARTED`.
- 1. Now click "**Open Web UI**" and follow the authentication process.
- 1. Once you've signed in with Google and authorized the app, copy the code back in the web UI. You will get an empty response after you have send your token.
- 1. After that, you can close the web UI tab.
-
-Google Assistant should now be running on your Raspberry Pi!
-To test it, say "Ok Google", following by the command of your choice.
-
-### Troubleshooting
-
-#### Google Assistant is not working
-
-Google needs to be able to send data back to your Google Assistant SDK Add-on by sending webhooks to `https://yourdomain:yourport/api/google_assistant`.
-
-To do so, you need to make sure that your Home Assistant is accessible from the internet and that it's using `https` (SSL).
-
-#### The assistant voice volume is too low
-
-If the voice of the assistant is really low, you can ask it to increase the volume:
-- "Ok Google, set volume to maximum."
-- or "Ok Google, set volume to 85%."
-
-## Support
-
-Got questions?
-
-You have several options to get them answered:
-
-- The [Home Assistant Discord Chat Server][discord].
-- The Home Assistant [Community Forum][forum].
-- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
-
-In case you've found a bug, please [open an issue on our GitHub][issue].
-
-[discord]: https://discord.gg/c5DvZ4e
-[documentation]: https://github.com/home-assistant/addons/blob/master/google_assistant/DOCS.md
-[forum]: https://community.home-assistant.io
-[google-actions-console]: https://console.actions.google.com/
-[google-assistant-api]: https://console.developers.google.com/apis/api/embeddedassistant.googleapis.com/overview
-[google-oauth-client]: https://console.developers.google.com/apis/credentials/oauthclient
-[google-oauth-concent]: https://console.developers.google.com/apis/credentials/consent
-[google-platform-project]: https://console.cloud.google.com/project
-[issue]: https://github.com/home-assistant/addons/issues
-[reddit]: https://reddit.com/r/homeassistant
-[repository]: https://github.com/hassio-addons/repository
-[samba-addon]: https://github.com/home-assistant/addons/tree/master/samba
diff --git a/google_assistant/Dockerfile b/google_assistant/Dockerfile
deleted file mode 100644
index d9b7ab13797..00000000000
--- a/google_assistant/Dockerfile
+++ /dev/null
@@ -1,37 +0,0 @@
-ARG BUILD_FROM
-FROM $BUILD_FROM
-
-ARG GOOGLE_GRPC_VERSION
-ARG GOOGLE_LIBRARY_VERSION
-ARG GOOGLE_SDK_VERSION
-ARG GOOGLE_AUTH_VERSION
-ARG REQUESTS_OAUTHLIB_VERSION
-ARG CHERRYPY_VERSION
-
-# Install packages
-RUN apt-get update \
- && apt-get install -y --no-install-recommends \
- libportaudio2 \
- libasound2-plugins \
- pulseaudio-utils \
- python3 \
- python3-dev \
- build-essential \
- && curl --silent --show-error --retry 5 \
- "https://bootstrap.pypa.io/get-pip.py" \
- | python3 \
- && pip3 install --no-cache-dir \
- cherrypy=="${CHERRYPY_VERSION}" \
- google-assistant-grpc=="${GOOGLE_GRPC_VERSION}" \
- google-assistant-library=="${GOOGLE_LIBRARY_VERSION}" \
- google-assistant-sdk=="${GOOGLE_SDK_VERSION}" \
- google-auth=="${GOOGLE_AUTH_VERSION}" \
- requests_oauthlib=="${REQUESTS_OAUTHLIB_VERSION}" \
- && apt-get remove -y --purge \
- python3-dev \
- build-essential \
- && apt-get clean -y \
- && rm -rf /var/lib/apt/lists/*
-
-# Copy data
-COPY rootfs /
diff --git a/google_assistant/README.md b/google_assistant/README.md
deleted file mode 100644
index 3ced66bc896..00000000000
--- a/google_assistant/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Home Assistant Add-on: Google Assistant SDK
-
-A virtual personal assistant developed by Google.
-
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-
-## About
-
-[Google Assistant][google-assistant] is an AI-powered voice assistant that runs on the Raspberry Pi and x86 platforms and interact via the [DialogFlow][dialogflow-integration] integration with Home-Assistant. You can also use [Google Actions][google-actions] to extend its functionality.
-
-This add-on allows you to access Google Assistant using the microphone and speaker attached to the computer or device running Home Assistant. You can say "Ok Google" followed by your command, and Google Assistant will answer your request.
-
-## ℹ️ Integration your mobile or Google/Nest Home with Home Assistant
-
-If you want to use Google Assistant (for example, from your phone or Google Home device) to interact with your Home Assistant managed devices, then you want the [Google Assistant integration][google-assistant-integration].
-
-[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[dialogflow-integration]: https://www.home-assistant.io/integrations/dialogflow/
-[google-actions]: https://actions.google.com/
-[google-assistant-integration]: https://www.home-assistant.io/integrations/google_assistant/
-[google-assistant]: https://assistant.google.com/
-[i386-shield]: https://img.shields.io/badge/i386-no-red.svg
-[aarch64-shield]: https://img.shields.io/badge/aarch64-no-red.svg
diff --git a/google_assistant/build.yaml b/google_assistant/build.yaml
deleted file mode 100644
index 543b6f7ace1..00000000000
--- a/google_assistant/build.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-build_from:
- amd64: ghcr.io/home-assistant/amd64-base-debian:buster
- armhf: ghcr.io/home-assistant/armhf-base-debian:buster
- armv7: ghcr.io/home-assistant/armv7-base-debian:buster
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
-args:
- CHERRYPY_VERSION: 18.1.1
- GOOGLE_AUTH_VERSION: 1.6.3
- GOOGLE_GRPC_VERSION: 0.2.0
- GOOGLE_LIBRARY_VERSION: 1.0.0
- GOOGLE_SDK_VERSION: 0.5.0
- REQUESTS_OAUTHLIB_VERSION: 1.2.0
diff --git a/google_assistant/config.yaml b/google_assistant/config.yaml
deleted file mode 100644
index 5af495a1d4d..00000000000
--- a/google_assistant/config.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-version: 2.5.0
-slug: google_assistant
-name: Google Assistant SDK
-description: A virtual personal assistant developed by Google
-url: >-
- https://github.com/home-assistant/addons/tree/master/google_assistant
-advanced: true
-arch:
- - armhf
- - armv7
- - amd64
-audio: true
-image: homeassistant/{arch}-addon-google_assistant
-init: false
-map:
- - share
-options:
- project_id: null
- client_secrets: google_assistant.json
- model_id: null
- feedback:
- enable: false
- volume: 80
-ports:
- 9324/tcp: 9324
-schema:
- project_id: str
- client_secrets: str
- model_id: str
- feedback:
- enable: bool
- volume: int(0,100)
-stage: experimental
-webui: http://[HOST]:[PORT:9324]
diff --git a/google_assistant/icon.png b/google_assistant/icon.png
deleted file mode 100644
index 4bade319b4f..00000000000
Binary files a/google_assistant/icon.png and /dev/null differ
diff --git a/google_assistant/logo.png b/google_assistant/logo.png
deleted file mode 100644
index 78bad829866..00000000000
Binary files a/google_assistant/logo.png and /dev/null differ
diff --git a/google_assistant/rootfs/etc/services.d/google-assistant/finish b/google_assistant/rootfs/etc/services.d/google-assistant/finish
deleted file mode 100755
index 5a23d05348c..00000000000
--- a/google_assistant/rootfs/etc/services.d/google-assistant/finish
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bashio
-# ==============================================================================
-# Take down the S6 supervision tree when service fails
-# s6-overlay docs: https://github.com/just-containers/s6-overlay
-# ==============================================================================
-
-if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
- exec /run/s6/basedir/bin/halt
-fi
-
-bashio::log.info "Service restart after closing"
diff --git a/google_assistant/rootfs/etc/services.d/google-assistant/run b/google_assistant/rootfs/etc/services.d/google-assistant/run
deleted file mode 100755
index cacb259147b..00000000000
--- a/google_assistant/rootfs/etc/services.d/google-assistant/run
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# ==============================================================================
-# Start Google Assistant service
-# ==============================================================================
-CLIENT_JSON=/data/client.json
-CRED_JSON=/data/cred.json
-
-CLIENT_SECRETS=$(bashio::config 'client_secrets')
-MODEL_ID=$(bashio::config 'model_id')
-PROJECT_ID=$(bashio::config 'project_id')
-FEEDBACK=$(bashio::config 'feedback')
-
-# check if a new assistant file exists
-if bashio::fs.file_exists "/share/${CLIENT_SECRETS}"; then
- bashio::log.info "Installing/Updating service client_secrets file"
- cp -f "/share/${CLIENT_SECRETS}" "${CLIENT_JSON}"
-fi
-
-if ! bashio::fs.file_exists "${CRED_JSON}" && bashio::fs.file_exists "${CLIENT_JSON}"; then
- bashio::log.info "Starting WebUI for handling OAuth2..."
- python3 /usr/bin/hassio_oauth.py "${CLIENT_JSON}" "${CRED_JSON}"
-elif ! bashio::fs.file_exists "${CRED_JSON}"; then
- bashio::exit.nok "You need initialize Google Assistant with a client secret JSON!"
-fi
-
-bashio::log.info "Starting Home Assistant GAssisant SDK..."
-exec python3 /usr/bin/hassio_gassistant.py \
- "${CRED_JSON}" "${PROJECT_ID}" "${MODEL_ID}" "${FEEDBACK}"
diff --git a/google_assistant/rootfs/usr/bin/hassio_gassistant.py b/google_assistant/rootfs/usr/bin/hassio_gassistant.py
deleted file mode 100644
index 92f9f8f8c0b..00000000000
--- a/google_assistant/rootfs/usr/bin/hassio_gassistant.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""Home Assistant Google Assistant."""
-import json
-import sys
-from pathlib import Path
-import subprocess
-import json
-import google.oauth2.credentials
-
-from google.assistant.library import Assistant
-from google.assistant.library.event import EventType
-from google.assistant.library.device_helpers import register_device
-
-DEVICE_CONFIG = "/data/device.json"
-
-PACAT_MAX_VOLUME = 65536
-
-feedback = json.loads(sys.argv[4])
-feedback_volume = feedback.get("volume", 0) * PACAT_MAX_VOLUME // 100
-
-def play_sound(sound_file):
- if feedback["enable"] and feedback_volume > 0:
- subprocess.Popen(["paplay", "--volume={v}".format(v=feedback_volume), "/usr/share/sounds/{f}".format(f=sound_file)])
-
-def process_event(event):
- if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
- play_sound("start_sound.wav")
- print()
-
- if event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
- play_sound("end_sound.wav")
-
- try:
- print(event)
- except UnicodeEncodeError as err:
- print("Can't print event: {}".format(err))
-
- if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED and event.args and not event.args['with_follow_on_turn']):
- print()
-
-
-if __name__ == '__main__':
- cred_json = Path(sys.argv[1])
- device_json = Path(DEVICE_CONFIG)
-
- # Open credentials
- print("OAuth with Google")
- with cred_json.open('r') as data:
- credentials = google.oauth2.credentials.Credentials(token=None, **json.load(data))
-
- # Read device info
- print("Initialize device infos")
- if device_json.exists():
- with device_json.open('r') as data:
- device_info = json.load(data)
-
- device_model_id = device_info['model_id']
- last_device_id = device_info.get('last_device_id', None)
- else:
- device_model_id = sys.argv[3]
- last_device_id = None
-
- # Run assistant
- print("Run Google Assistant SDK")
- with Assistant(credentials, device_model_id) as assistant:
- events = assistant.start()
- device_id = assistant.device_id
-
- print("device_model_id: {}".format(device_model_id))
- print("device_id: {}".format(device_id))
-
- # Register device
- if last_device_id != device_id:
- register_device(sys.argv[2], credentials, device_model_id, device_id)
- with device_json.open('w') as dev_file:
- json.dump({
- 'last_device_id': device_id,
- 'model_id': device_model_id,
- }, dev_file)
-
- for event in events:
- process_event(event)
-
- print("Close Google Assistant SDK")
diff --git a/google_assistant/rootfs/usr/bin/hassio_oauth.py b/google_assistant/rootfs/usr/bin/hassio_oauth.py
deleted file mode 100644
index e2c3730d1c0..00000000000
--- a/google_assistant/rootfs/usr/bin/hassio_oauth.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""Run small webservice for oath."""
-import json
-import sys
-from pathlib import Path
-import threading
-import time
-
-import cherrypy
-from requests_oauthlib import OAuth2Session
-from google.oauth2.credentials import Credentials
-
-HEADERS = str("""
-
-
-
-""")
-
-class oauth2Site(object):
- """Website for handling oauth2."""
-
- def __init__(self, user_data, cred_file):
- """Init webpage."""
- self.cred_file = cred_file
- self.user_data = user_data
-
- self.oauth2 = OAuth2Session(
- self.user_data['client_id'],
- redirect_uri='urn:ietf:wg:oauth:2.0:oob',
- scope="https://www.googleapis.com/auth/assistant-sdk-prototype"
- )
-
- self.auth_url, _ = self.oauth2.authorization_url(self.user_data['auth_uri'], access_type='offline', prompt='consent')
-
- @cherrypy.expose
- def index(self):
- """Landing page."""
- return str("""
- {headers}
-
-
-
- """).format(url=self.auth_url, headers=HEADERS)
-
- @cherrypy.expose
- def token(self, token):
- """Read access token and process it."""
- try:
- self.oauth2.fetch_token(self.user_data['token_uri'], client_secret=self.user_data['client_secret'], code=token)
- except Exception as e:
- cherrypy.log("Error with the given token: {error}".format(error=str(e)))
- cherrypy.log("Restarting authentication process.")
- raise cherrypy.HTTPRedirect('/')
-
- # create credentials
- credentials = Credentials(
- self.oauth2.token['access_token'],
- refresh_token=self.oauth2.token.get('refresh_token'),
- token_uri=self.user_data['token_uri'],
- client_id=self.user_data['client_id'],
- client_secret=self.user_data['client_secret'],
- scopes=self.oauth2.scope
- )
-
- # write credentials json file
- with self.cred_file.open('w') as json_file:
- json_file.write(json.dumps({
- 'refresh_token': credentials.refresh_token,
- 'token_uri': credentials.token_uri,
- 'client_id': credentials.client_id,
- 'client_secret': credentials.client_secret,
- 'scopes': credentials.scopes,
- }))
-
- threading.Thread(target=self.exit_app).start()
- return str("""
- {headers}
-
-
-
-
-
Google Assistant SDK
-
Setup completed.
-
You can now close this window.
-
-
-
- """).format(url=self.auth_url, headers=HEADERS)
-
- def exit_app(self):
- time.sleep(2)
- cherrypy.engine.exit()
-
-def hide_access_logs():
- """Hide file access logging for cleaner logs"""
- access_log = cherrypy.log.access_log
- for handler in tuple(access_log.handlers):
- access_log.removeHandler(handler)
-
-if __name__ == '__main__':
- oauth_json = Path(sys.argv[1])
- cred_json = Path(sys.argv[2])
-
- with oauth_json.open('r') as data:
- user_data = json.load(data)['installed']
-
- hide_access_logs()
- cherrypy.config.update({'server.socket_port': 9324, 'server.socket_host': '0.0.0.0'})
- cherrypy.quickstart(oauth2Site(user_data, cred_json), config={
- '/static': {
- 'tools.staticdir.on': True,
- 'tools.staticdir.dir': '/usr/share/public'
- }
- })
diff --git a/google_assistant/rootfs/usr/share/public/css/style.css b/google_assistant/rootfs/usr/share/public/css/style.css
deleted file mode 100644
index 46c3517424d..00000000000
--- a/google_assistant/rootfs/usr/share/public/css/style.css
+++ /dev/null
@@ -1,97 +0,0 @@
-body {
- font-family: 'Roboto', sans-serif;
- background-color: #fafafa;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.card {
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
- background-color: #ffffff;
- color: #212121;
- border-radius: 2px;
- margin: 15px;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- width: 400px;
- max-width: 90vw;
-}
-
-.card .card-content {
- padding: 15px 25px;
- border-bottom: 1px solid #bdbdbd;
-}
-
-.card .card-actions {
- padding: 15px 25px;
-}
-
-h1 {
- font-size: 24px;
-}
-
-img {
- max-height: 60px;
-}
-
-ol {
- margin: 28px 0 0 0;
- padding: 0;
- list-style-type: none;
-}
-
-ol li {
- counter-increment: step-counter;
- margin-bottom: 20px;
- display: flex;
- align-items: center;
-}
-
-ol li::before {
- content: counter(step-counter);
- margin-right: 5px;
- padding: 3px 8px;
- border-radius: 9999px;
- border: 1px solid #bdbdbd;
-}
-
-input {
- border: none;
- box-sizing: border-box;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- border-bottom: 1px solid black;
- font-size: 14px;
- flex-grow: 1;
- height: 30px;
- width: 100%;
- background: transparent;
- outline: none;
- transition: border-bottom 0.225s ease;
-}
-
-input:focus {
- border-bottom: 2px solid black;
-}
-
-button {
- font-size: 16px;
- padding: 8px 10px;
- background-color: transparent;
- border: none;
- color: #03a9f4;
- cursor: pointer;
- border-radius: 4px;
- outline: none;
- transition: background-color 0.225s ease;
-}
-
-button:hover {
- background-color: #03a8f425;
-}
-
-button:active {
- background-color: #03a8f44f;
-}
diff --git a/google_assistant/rootfs/usr/share/public/favicon.ico b/google_assistant/rootfs/usr/share/public/favicon.ico
deleted file mode 100644
index 6d12158c18b..00000000000
Binary files a/google_assistant/rootfs/usr/share/public/favicon.ico and /dev/null differ
diff --git a/google_assistant/rootfs/usr/share/public/logo.png b/google_assistant/rootfs/usr/share/public/logo.png
deleted file mode 100644
index 78bad829866..00000000000
Binary files a/google_assistant/rootfs/usr/share/public/logo.png and /dev/null differ
diff --git a/google_assistant/rootfs/usr/share/sounds/end_sound.wav b/google_assistant/rootfs/usr/share/sounds/end_sound.wav
deleted file mode 100755
index 3374c29738f..00000000000
Binary files a/google_assistant/rootfs/usr/share/sounds/end_sound.wav and /dev/null differ
diff --git a/google_assistant/rootfs/usr/share/sounds/start_sound.wav b/google_assistant/rootfs/usr/share/sounds/start_sound.wav
deleted file mode 100755
index c41781efd90..00000000000
Binary files a/google_assistant/rootfs/usr/share/sounds/start_sound.wav and /dev/null differ
diff --git a/google_assistant/translations/en.yaml b/google_assistant/translations/en.yaml
deleted file mode 100644
index 8383294621c..00000000000
--- a/google_assistant/translations/en.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-configuration:
- project_id:
- name: Project ID
- description: >-
- Project ID of the project you've created at Google for this add-on.
- client_secrets:
- name: Client Secrets
- description: >-
- The name of the client secrets file to you've downloaded from Google and
- placed in your `/share` folder.
- model_id:
- name: Model ID
- description: >-
- The ID of the model you've registered at Google for this add-on.
- feedback:
- name: Feedback
- description: Control feedback options
-network:
- 9324/tcp: The port for the Webserver
diff --git a/letsencrypt/CHANGELOG.md b/letsencrypt/CHANGELOG.md
index 370b37a2c40..0cfaa7b3321 100644
--- a/letsencrypt/CHANGELOG.md
+++ b/letsencrypt/CHANGELOG.md
@@ -1,5 +1,269 @@
# Changelog
+## 6.0.4
+
+- Require `dns.provider` if DNS challenge is set
+- Clean up cache files from the build to reduce image size
+
+## 6.0.3
+
+- Fix issuing certificates when `acme_root_ca_cert` is set
+
+## 6.0.2
+
+- Fix propagation seconds not being correctly applied to certbot-dns-multi providers
+
+## 6.0.1
+
+- Fix Route 53 DNS provider failing with "Missing Region" error
+- Add optional `aws_region` configuration option (defaults to `us-east-1`)
+
+## 6.0.0
+
+This release migrates most DNS challenge providers from individual certbot
+plugins to [certbot-dns-multi](https://github.com/alexzorin/certbot-dns-multi),
+which uses the [lego ACME library](https://go-acme.github.io/lego/) under the
+hood. This significantly reduces maintenance burden and makes it easier to
+support new DNS providers in the future. Existing configurations will continue
+to work for most providers without changes. A few provider-specific options
+that have no lego equivalent have been removed or are now ignored - see the
+breaking changes below.
+
+### Breaking changes
+
+- Remove `cloudns_sub_auth_user` option (not supported by lego)
+- Remove `rfc2136_sign_query` option (not supported by lego)
+- Remove `transip_global_key` option (not supported by lego)
+- Remove `linode_version` option: only Linode API v4 is supported
+- Ignore `dreamhost_baseurl` option (not supported by lego, default URL is used)
+- Ignore `gandi_sharing_id`, `ionos_endpoint`, `joker_domain` options (not supported by lego)
+- Hetzner option `hetzner_api_token` now requires Hetzner Cloud API token, old Hetzner DNS token is no longer supported
+- Drop unsupported armhf, armv7, and i386 architectures
+
+### Other changes
+
+- Add generic `dns-lego` provider for any lego-supported DNS provider
+ - Specify `lego_provider` (lego provider name) and `lego_env` (list of KEY=VALUE env vars)
+ - Supports 180+ DNS providers without needing to add new certbot plugins
+- Replace individual certbot DNS plugins with certbot-dns-multi (lego-based)
+- Migrate from Alpine to Debian base image (trixie-2025.12.2) for lego support
+- Deprecate dns-azure provider: uses legacy certbot-dns-azure plugin
+- Deprecate dns-he provider: uses legacy certbot-dns-hurricane-electric plugin
+
+## 5.4.10
+
+- Update certbot-dns-desec to 1.3.1
+
+## 5.4.9
+
+- Fix pending issue in 5.4.8 with trust store when using a custom ACME server
+
+## 5.4.8
+
+- Further improve root certificate handling when using a custom ACME server
+
+## 5.4.7
+
+- Fix root certificate format when using custom ACME server
+
+## 5.4.6
+
+- Fix custom ACME server for DNS challenge (fixes #1769)
+
+## 5.4.5
+
+- Update certbot-dns-directadmin to 1.0.15
+
+## 5.4.4
+
+- Update certbot to 3.3.0
+- Update acme to 3.3.0
+- Update cryptography to 44.0.2
+
+## 5.4.3
+
+- Update certbot-dns-websupport to 3.0.0
+- Re-enable certbot-dns-websupport
+
+## 5.4.2
+
+- Update certbot-dns-dynu to 0.0.8
+- Update certbot-dns-gandi to 1.6.1
+ (incl. switch back to a renamed updated original version)
+
+## 5.4.1
+
+- Fix TransIP global_key handling
+
+## 5.4.0
+
+- Add additional arguments to certbot (dry-run, test-cert, verbose)
+- Switch gandi-dns to a maintained version (certbot-plugin-gandi-modern)
+- Refactor scripts
+- Improve documentation
+- Refactor configuration and align with documentation
+
+## 5.3.3
+
+- Re-enabled certbot-dns-mijn-host
+
+## 5.3.2
+
+- Update certbot to 3.2.0
+- Update acme to 3.2.0
+- Update certbot-dns-inwx to 3.0.2
+
+## 5.3.1
+
+- Add Eurodns DNS support
+
+## 5.3.0
+
+- Disabled certbot-dns-mijn-host (Breaking change)
+ - issue: [mijnhost/certbot-dns-mijn-host#8](https://github.com/mijnhost/certbot-dns-mijn-host/issues/8)
+- Disabled certbot-dns-websupport (Breaking change)
+ - issue: [johnybx/certbot-dns-websupport#1](https://github.com/johnybx/certbot-dns-websupport/issues/1)
+- Update to Python 3.13
+- Update to Alpine 3.21
+- Update certbot to 3.1.0
+- Update acme to 3.1.0
+- Update cryptography to 44.0.1
+- Update certbot-dns-azure to 2.6.1
+- Update certbot-dns-directadmin to 10.0.13
+- Update certbot-dns-duckdns to 1.5
+- Update certbot-dns-dynu to 0.0.6
+- Update certbot-dns-inwx to 3.0.1
+- Update certbot-dns-ionos to 2024.11.9
+- Update certbot-dns-norisnetwork to 0.3.0
+- Update certbot-dns-porkbun to 0.9.1
+- Update certbot-dns-netcup to 1.4.4
+- Update certbot-dns-njalla to 2.0.2
+- Update the remaining dns challenges with DNS_PROVIDER placeholder
+
+## 5.2.12
+
+- Add rfc2136_sign_query parameter to config.yaml
+
+## 5.2.11
+
+- Use a newer, maintained Hurricane Electric plugin.
+
+## 5.2.10
+
+- Add transip global_key parameter to config.yaml
+
+## 5.2.9
+
+- Update certbot-dns-infomaniak to 0.2.3
+
+## 5.2.8
+
+- Add transip global_key parameter to support authentication without IP whitelist requirements
+
+## 5.2.7
+
+- Add mijn.host DNS support
+
+## 5.2.6
+
+- Fix dns-loopia username error
+
+## 5.2.5
+
+- Update certbot-dns-directadmin to 1.0.12
+
+## 5.2.4
+
+- Add Loopia DNS support
+
+## 5.2.3
+
+- Fix syntax error in run script
+
+## 5.2.2
+
+- Add IONOS DNS support
+
+## 5.2.1
+
+- Revert Cryptography to 42.0.8 to avoid deprecation warnings
+
+## 5.2.0
+
+- Update Certbot/ACME to 2.11.0 & update all plugins to their latest version
+- Update to Python 3.12
+- Update to Alpine 3.20
+
+## 5.1.4
+
+- Drop Google Domains support (the new operator Squarespace has no ACME support)
+
+## 5.1.3
+
+- Add godaddy.com DNS support
+
+## 5.1.2
+
+- Fixes subdomain DNS challenge not working for Simply.com
+
+## 5.1.1
+
+- Add Simply.com DNS support
+
+## 5.1.0
+
+- Add external account binding support
+
+## 5.0.27
+
+- Add Plesk DNS challenge support
+
+## 5.0.26
+
+- Add noris network DNS challenge support
+
+## 5.0.25
+
+- Add DigitalOcean propagation-seconds support
+
+## 5.0.24
+
+- Fix Gandi DNS support using API key
+
+## 5.0.23
+
+- Fix missing domain configuration for joker.com DNS challenge
+
+## 5.0.22
+
+- Add joker.com DNS challenge support
+
+## 5.0.21
+
+- Fix configuration to make list of provider parsable again
+
+## 5.0.20
+
+- Fix file-structure.sh script
+- Fix domainoffensive plug-in installation
+
+## 5.0.19
+
+- Add domainoffensive challenge support
+
+## 5.0.18
+
+- Fix Gandi DNS support using API key
+- Add Gandi DNS support using token authentication
+
+## 5.0.17
+
+- Add WebSupport challenge support
+
+## 5.0.16
+
+- Add Dynu challenge support
+
## 5.0.15
- Add easyDNS challenge support
diff --git a/letsencrypt/DOCS.md b/letsencrypt/DOCS.md
index 3a6840324e1..586831a9caf 100644
--- a/letsencrypt/DOCS.md
+++ b/letsencrypt/DOCS.md
@@ -1,20 +1,20 @@
-# Home Assistant Add-on: Letsencrypt
+# Home Assistant App: Letsencrypt
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "letsencrypt" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "letsencrypt" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The Letsencrypt add-on can be configured via the add-on interface.
+The Letsencrypt app can be configured via the app interface.
The configuration via YAML is also possible, see the examples below.
-Navigate in your Home Assistant frontend to the add-ons overview page at
-**Settings** -> **Add-ons**, and pick the **Let's Encrypt** add-on. On the top,
+Navigate in your Home Assistant frontend to the apps overview page at
+**Settings** > **Apps**, and pick the **Let's Encrypt** app. On the top,
pick the **Configuration** page.
Provide the domain names to issue certificates for. Additionally, provide the
@@ -26,20 +26,23 @@ There are two options to obtain certificates.
### 1. HTTP challenge
- Requires Port 80 to be available from the internet and your domain assigned to the externally assigned IP address
-- Doesn’t allow wildcard certificates (*.yourdomain.com).
+- Doesn’t allow wildcard certificates (*.domain.tld).
### 2. DNS challenge
- Requires you to use one of the supported DNS providers (See "Supported DNS providers" below)
-- Allows to request wildcard certificates (*.yourdomain.com)
+- Allows to request wildcard certificates (*.domain.tld)
- Doesn’t need you to open a port to your Home Assistant host on your router.
### DNS providers
+
+
- Supported DNS providerss
+ Supported DNS providers
```txt
+dns-lego (generic, supports any lego DNS provider)
dns-azure
dns-cloudflare
dns-cloudns
@@ -48,28 +51,42 @@ dns-digitalocean
dns-directadmin
dns-dnsimple
dns-dnsmadeeasy
-dns-duckdns
+dns-domainoffensive
dns-dreamhost
+dns-duckdns
+dns-dynu
+dns-easydns
+dns-eurodns
+dns-gandi
dns-gehirn
+dns-godaddy
dns-google
+dns-he
dns-hetzner
dns-infomaniak
+dns-inwx
+dns-ionos
+dns-joker
dns-linode
+dns-loopia
dns-luadns
+dns-mijn-host
+dns-namecheap
+dns-netcup
dns-njalla
+dns-noris
dns-nsone
dns-ovh
+dns-plesk
+dns-porkbun
dns-rfc2136
dns-route53
dns-sakuracloud
-dns-namecheap
-dns-netcup
-dns-gandi
+dns-simply
dns-transip
-dns-inwx
-dns-porkbun
-dns-easydns
+dns-websupport
```
+
@@ -77,66 +94,93 @@ dns-easydns
```yaml
propagation_seconds: 60
+lego_env: []
+lego_provider: ''
+aws_access_key_id: ''
+aws_region: ''
+aws_secret_access_key: ''
azure_config: ''
-cloudflare_email: ''
cloudflare_api_key: ''
cloudflare_api_token: ''
+cloudflare_email: ''
cloudns_auth_id: ''
-cloudns_sub_auth_id: ''
-cloudns_sub_auth_user: ''
cloudns_auth_password: ''
+cloudns_sub_auth_id: ''
desec_token: ''
digitalocean_token: ''
+directadmin_password: ''
directadmin_url: ''
directadmin_username: ''
-directadmin_password: ''
dnsimple_token: ''
dnsmadeeasy_api_key: ''
dnsmadeeasy_secret_key: ''
+domainoffensive_token: ''
+dreamhost_api_key: ''
duckdns_token: ''
+dynu_auth_token: ''
+easydns_endpoint: ''
+easydns_key: ''
+easydns_token: ''
+eurodns_apiKey: ''
+eurodns_applicationId: ''
+gandi_api_key: ''
+gandi_token: ''
+gehirn_api_secret: ''
+gehirn_api_token: ''
+godaddy_key: ''
+godaddy_secret: ''
google_creds: ''
-google_domains_access_token: ''
-google_domains_zone: ''
+he_pass: ''
+he_user: ''
hetzner_api_token: ''
-gehirn_api_token: ''
-gehirn_api_secret: ''
infomaniak_api_token: ''
+inwx_password: ''
+inwx_shared_secret: ''
+inwx_username: ''
+ionos_prefix: ''
+ionos_secret: ''
+joker_password: ''
+joker_username: ''
linode_key: ''
linode_version: ''
+loopia_password: ''
+loopia_user: ''
luadns_email: ''
luadns_token: ''
+mijn_host_api_key: ''
+namecheap_api_key: ''
+namecheap_username: ''
+netcup_api_key: ''
+netcup_api_password: ''
+netcup_customer_id: ''
njalla_token: ''
+noris_token: ''
nsone_api_key: ''
-ovh_endpoint: ''
ovh_application_key: ''
ovh_application_secret: ''
ovh_consumer_key: ''
-rfc2136_server: ''
-rfc2136_port: ''
+ovh_endpoint: ''
+plesk_api_url: ''
+plesk_password: ''
+plesk_username: ''
+porkbun_key: ''
+porkbun_secret: ''
+rfc2136_algorithm: ''
rfc2136_name: ''
+rfc2136_port: ''
rfc2136_secret: ''
-rfc2136_algorithm: ''
-aws_access_key_id: ''
-aws_secret_access_key: ''
-sakuracloud_api_token: ''
+rfc2136_server: ''
+rfc2136_sign_query: false
sakuracloud_api_secret: ''
-namecheap_username: ''
-namecheap_api_key: ''
-netcup_customer_id: ''
-netcup_api_key: ''
-netcup_api_password: ''
-gandi_api_key: ''
-gandi_sharing_id: ''
-transip_username: ''
+sakuracloud_api_token: ''
+simply_account_name: ''
+simply_api_key: ''
transip_api_key: ''
-inwx_username: ''
-inwx_password: ''
-inwx_shared_secret: ''
-porkbun_key: ''
-porkbun_secret: ''
-dreamhost_api_baseurl: ''
-dreamhost_api_key: ''
+transip_username: ''
+websupport_identifier: ''
+websupport_secret_key: ''
```
+
### Configure certificate files
@@ -144,15 +188,15 @@ dreamhost_api_key: ''
The certificate files will be available within the "ssl" share after successful
request of the certificates.
-By default other addons are referring to the correct path of the certificates.
-You can in addition find the files via the "samba" addon within the "ssl" share.
+By default, other apps are referring to the correct path of the certificates.
+You can in addition find the files via the **Samba** app within the "ssl" share.
-For example, to use the certificates provided by this add-on to enable TLS on
+For example, to use the certificates provided by this app to enable TLS on
Home Assistant in the default paths, add the following lines to Home
Assistant's main configuration file, `configuration.yaml`:
```yaml
-# TLS with letsencrypt add-on
+# TLS with letsencrypt app
http:
server_port: 443
ssl_certificate: /ssl/fullchain.pem
@@ -161,25 +205,25 @@ http:
### Create & renew certificates
-The letsencrypt add-on creates the certificates once it is started: navigate
-to **Settings** -> **Add-ons**, pick the **Let's Encrypt** add-on, click the
-**START** button on the bottom. The add-on stops once the certificates are
+The letsencrypt app creates the certificates once it is started: navigate
+to **Settings** > **Apps**, pick the **Let's Encrypt** app, click the
+**START** button on the bottom. The app stops once the certificates are
created.
-Certificates are not renewed automatically by the plugin. The add-on has to be
-started again to renew certificates. If the add-on is started again, it checks
+Certificates are not renewed automatically by the plugin. The app has to be
+started again to renew certificates. If the app is started again, it checks
if the certificates are due for renewal. This is usually the case 30 days
before the certificates' due date. If the certificates are not due for renewal,
-the add-on terminates without changes. If the certificates are due for renewal,
+the app terminates without changes. If the certificates are due for renewal,
new certificates will be created.
-There are multiple ways how the add-on can be started to check/renew the
+There are multiple ways how the app can be started to check/renew the
certificates. One way to automate the certificate renewal it to configure a
renewal via [Home Assistant automation][haauto], and then restarting this
-automation every night via the [Supervisor Addon restart action][supervisorrestart].
+automation every night via the [Supervisor app restart action][supervisorrestart].
[haauto]: https://www.home-assistant.io/docs/automation/editor/
-[supervisorrestart]: https://www.home-assistant.io/integrations/hassio/#service-hassioaddon_restart
+[supervisorrestart]: https://www.home-assistant.io/integrations/hassio/#action-hassioaddon_restart
In this example, the automation will run every day at the chosen time, checking
if a renewal is due, and will request it if needed.
@@ -189,13 +233,14 @@ if a renewal is due, and will request it if needed.
Changing the ACME Server
-By default, The addon uses Let’s Encrypt’s default server at https://acme-v02.api.letsencrypt.org/. You can instruct the addon to use a different ACME server by providing the field `acme_server` with the URL of the server’s ACME directory:
+By default, the app uses [Let’s Encrypt’s default servers](https://letsencrypt.org/getting-started/). You can instruct the app to use a different ACME server by providing the field `acme_server` with the URL of the server’s ACME directory:
```yaml
acme_server: 'https://my.custom-acme-server.com'
```
If your custom ACME server uses a certificate signed by an untrusted certificate authority (CA), you can add the root certificate to the trust store by setting its content as an option:
+
```yaml
acme_server: 'https://my.custom-acme-server.com'
acme_root_ca_cert: |
@@ -204,6 +249,8 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
-----END CERTIFICATE-----
```
+When you specify a custom ACME server, the *Dry Run* and *Issue test certificates* options, which are intended for use with the [Let's Encrypt staging server](https://letsencrypt.org/docs/staging-environment/), are automatically disregarded.
+
@@ -215,13 +262,13 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
key_type: 'rsa'
```
- When the `key_type` parameter is not set, the add-on will attempt to auto-detect an existing certificate's key type or use `ecdsa` by default.
+ When the `key_type` parameter is not set, the app will attempt to auto-detect an existing certificate's key type or use `ecdsa` by default.
Selecting the ECDSA Elliptic Curve
-
+
You can choose from the following ECDSA elliptic curves: `secp256r1`, `secp384r1`
```yaml
@@ -233,15 +280,32 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
+
+ Set up external account binding
+
+ The ACME protocol (RFC 8555) defines an external account binding (EAB) field that ACME clients can use to access a specific account on the certificate authority (CA). Some CAs may require the client to utilize the EAB protocol to operate. You can add your EAB key ID and HMAC key through the config options `eab_kid` and `eab_hmac_key`.
+
+ ```yaml
+ eab_kid: 'key_id'
+ eab_hmac_key: 'AABBCCDD' #Base64url encoded key
+ ```
+
+
+
## Example Configurations
+**Important Note for UI Edit Mode:** These configuration examples are raw YAML configs.
+When using the UI edit mode (which is the default), and configuring DNS, you **must**
+only copy the attributes *underneath* the `dns:` key into the "DNS Provider configuration" field.
+Do NOT include the `dns:` key itself when pasting into the UI field, as this will cause parsing errors.
+
HTTP challenge
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: http
@@ -256,7 +320,7 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
@@ -268,13 +332,61 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
+
+ DNS challenge using generic lego provider
+
+The `dns-lego` provider lets you use **any** DNS provider supported by the
+[lego ACME library](https://go-acme.github.io/lego/dns/) - even those not
+listed as named providers in this documentation. You specify the lego provider
+name and its required environment variables directly.
+
+To find the provider name and required environment variables for your DNS
+provider, visit the
+[lego DNS providers documentation](https://go-acme.github.io/lego/dns/).
+
+Example using [acme-dns](https://go-acme.github.io/lego/dns/acme-dns/):
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-lego
+ lego_provider: acme-dns
+ lego_env:
+ - "ACME_DNS_API_BASE=http://10.0.0.8:4443"
+ - "ACME_DNS_STORAGE_PATH=/share/acme-dns-accounts.json"
+ propagation_seconds: 120
+ ```
+
+Example using [Hetzner](https://go-acme.github.io/lego/dns/hetzner/) (equivalent to using `dns-hetzner`):
+
+ ```yaml
+ dns:
+ provider: dns-lego
+ lego_provider: hetzner
+ lego_env:
+ - "HETZNER_API_TOKEN=your-api-token"
+ ```
+
+**Notes:**
+
+- Each `lego_env` entry must be in `KEY=VALUE` format. Values containing `=` signs are supported (e.g., `KEY=val=ue`).
+- For providers that require credential files, place the file in the `/share/` folder and reference it as `/share/filename` in the environment variable.
+- The `propagation_seconds` setting generates a timeout variable based on the uppercased provider name (e.g., `HETZNER_PROPAGATION_TIMEOUT`). If your provider uses a different variable prefix, you can include the correct timeout variable directly in `lego_env` and omit `propagation_seconds`.
+
+
+
RSA key
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
key_type: rsa
@@ -288,12 +400,12 @@ If your custom ACME server uses a certificate signed by an untrusted certificate
- Azure DNS challenge
+ Azure
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
@@ -304,7 +416,7 @@ dns:
Please copy your credentials file "azure.txt" into the "share" shared folder
on the Home Assistant host before starting the service. One way is to use the
-"Samba" add on to make the folder available via network or SSH Add-on. You
+**Samba** app to make the folder available via network or SSH App. You
can find information on the required file format in the [documentation][certbot-dns-azure-conf]
for the Certbot Azure plugin.
@@ -319,166 +431,109 @@ on the DNS zone to be used for authentication.
- Google Cloud DNS challenge
+ Cloudflare
+
+To use this plugin a Cloudflare API Token, restricted to the specific domain and operations are the recommended authentication option.
+The API Token used for Certbot requires only the `Zone:DNS:Edit` permission for the zone in which you want a certificate.
+
+Example credentials file using restricted API Token (recommended):
```yaml
- email: your.email@example.com
- domains:
- - home-assistant.io
- certfile: fullchain.pem
- keyfile: privkey.pem
- challenge: dns
dns:
- provider: dns-google
- google_creds: google.json
+ provider: dns-cloudflare
+ cloudflare_api_token: 0123456789abcdef0123456789abcdef01234
```
-Please copy your credentials file "google.json" into the "share" shared folder on the Home Assistant host before starting the service.
-
-One way is to use the "Samba" add on to make the folder available via network or SSH Add-on.
+Previously, Cloudflare’s “Global API Key” was used for authentication. However this key can access the entire Cloudflare API for all domains in your account, meaning it could cause a lot of damage if leaked.
-The credential file can be created and downloaded when creating the service user within the Google cloud.
-You can find additional information regarding the required permissions in the "credentials" section here:
+Example credentials file using Global API Key (NOT RECOMMENDED):
-
+ ```yaml
+ dns:
+ provider: dns-cloudflare
+ cloudflare_email: cloudflare@example.com
+ cloudflare_api_key: 0123456789abcdef0123456789abcdef01234
+ ```
- Google Domains DNS challenge
+ ClouDNS
+
+In order to use a domain with this challenge, you first need to log into your control panel and
+create a new HTTP API user from the `API & Resellers` page on top of your control panel.
```yaml
email: your.email@example.com
domains:
- - subdomain.home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-google-domains
- google_domains_access_token: XXXX
- google_domains_zone: home-assistant.io
+ provider: dns-cloudns
+ cloudns_auth_id: 12345
+ cloudns_auth_password: ******
```
-To obtain the ACME DNS API token follow the instructions here:
-
-
-
-The optional `google_domains_zone` option specifies the domain name registered with Google Domains. If not specified, it is guessed based on the public suffix list.
-
-
-
-
- Infomaniak DNS challenge
+API Users have full account access. It is recommended to create an API Sub-user, which can be limited in scope, use `sub-auth-id` as follows:
```yaml
email: your.email@example.com
domains:
- - subdomain.home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-infomaniak
- infomaniak_api_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ provider: dns-cloudns
+ cloudns_sub_auth_id: 12345
+ cloudns_auth_password: ******
```
-To obtain the DNS API token follow the instructions here:
-
-
-
-Choose "Domain" as the scope.
-
- route53 DNS challenge
+ deSEC.io
+
+ You need a deSEC API token with sufficient permission for performing the required DNS changes on your domain.
+ If you don't have a token yet, an easy way to obtain one is by logging into your account at deSEC.io.
+ Navigate to "Token Management" and create a new one.
+ It's good practice to restrict the token permissions as much as possible, e.g. by setting the maximum unused period to four months.
+ This way, the token will expire if it is not continuously used to renew your certificate.
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-route53
- aws_access_key_id: 0123456789ABCDEF0123
- aws_secret_access_key: 0123456789abcdef0123456789/abcdef0123456
- ```
-
-For security reasons, don't use your main account's credentials. Instead, add a new [AWS user](https://console.aws.amazon.com/iam/home?#/users) with _Access Type: Programmatic access_ and use that user's access key. Assign a minimum [policy](https://console.aws.amazon.com/iam/home?#/policies$new?step=edit) like the following example. Make sure to replace the Resource ARN in the first statement to your domain's hosted zone ARN or use _*_ for all.
-
- ```json
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Sid": "ChangeSpecificDomainsRecordSet",
- "Effect": "Allow",
- "Action": "route53:ChangeResourceRecordSets",
- "Resource": "arn:aws:route53:::hostedzone/01234567890ABC"
- },
- {
- "Sid": "ListAllHostedZones",
- "Effect": "Allow",
- "Action": "route53:ListHostedZones",
- "Resource": "*"
- },
- {
- "Sid": "ReadChanges",
- "Effect": "Allow",
- "Action": "route53:GetChange",
- "Resource": "arn:aws:route53:::change/*"
- }
- ]
- }
- ```
-
-
-
-
- CloudFlare
-
-Previously, Cloudflare’s “Global API Key” was used for authentication, however this key can access the entire Cloudflare API for all domains in your account, meaning it could cause a lot of damage if leaked.
-
-Cloudflare’s newer API Tokens can be restricted to specific domains and operations, and are therefore now the recommended authentication option.
-The API Token used for Certbot requires only the `Zone:DNS:Edit` permission for the zone in which you want a certificate.
-
-Example credentials file using restricted API Token (recommended):
- ```yaml
- dns:
- provider: dns-cloudflare
- cloudflare_api_token: 0123456789abcdef0123456789abcdef01234
- ```
-
-Example credentials file using Global API Key (not recommended):
- ```yaml
- dns:
- provider: dns-cloudflare
- cloudflare_email: cloudflare@example.com
- cloudflare_api_key: 0123456789abcdef0123456789abcdef01234
+ provider: dns-desec
+ desec_token: your-desec-access-token
```
- Linode
+ DigitalOcean
-To use this addon with Linode DNS, first [create a new API/access key](https://www.linode.com/docs/platform/api/getting-started-with-the-linode-api#get-an-access-token), with read/write permissions to DNS; no other permissions are needed. Newly keys will likely use API version '4.' **Important**: single quotes are required around the `linode_version` number; failure to do this will cause a type error (as the addon expects a string, not an integer).
+Use of this plugin requires a configuration file containing DigitalOcean API credentials, obtained from your DigitalOcean account’s [Applications & API Tokens page](https://cloud.digitalocean.com/settings/api/tokens).
- ```yaml
- email: you@mailprovider.com
+```yaml
+ email: mail@domain.tld
domains:
- - ha.yourdomain.com
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-linode
- linode_key: 865c9f462c7d54abc1ad2dbf79c938bc5c55575fdaa097ead2178ee68365ab3e
- linode_version: '4'
- ```
+ provider: dns-digitalocean
+ digitalocean_token: digitalocean-token
+```
+
+[Full Documentation](https://certbot-dns-digitalocean.readthedocs.io/en/stable/)
@@ -486,16 +541,19 @@ To use this addon with Linode DNS, first [create a new API/access key](https://w
DirectAdmin
It is recommended to create a login key in the DirectAdmin control panel to be used as value for directadmin_password.
-Instructions on how to create such key can be found at https://help.directadmin.com/item.php?id=523.
+Instructions on how to create such key can be found at .
Make sure to grant the following permissions:
+
- `CMD_API_LOGIN_TEST`
- `CMD_API_DNS_CONTROL`
- `CMD_API_SHOW_DOMAINS`
+- `CMD_API_DOMAIN_POINTER`
Username and password can also be used in case your DirectAdmin instance has no support for login keys.
Example configuration:
+
```yaml
email: mail@domain.tld
domains:
@@ -514,56 +572,53 @@ Example configuration:
- Namecheap
+ dnsimple
-To use this addon with Namecheap, you must first enable API access on your account. See "Enabling API Access" and "Whitelisting IP" [here](https://www.namecheap.com/support/api/intro/) for details and requirements.
-
-Example configuration:
+Use of this plugin requires a configuration file containing DNSimple API credentials, obtained from your DNSimple [account page](https://dnsimple.com/user).
- ```yaml
- email: your.email@example.com
+```yaml
+ email: mail@domain.tld
domains:
- - ha.yourdomain.com
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-namecheap
- namecheap_username: your-namecheap-username
- namecheap_api_key: 0123456789abcdef0123456789abcdef01234567
- ```
+ provider: dns-dnsimple
+ dnsimple_token: dnssimple-token
+```
+
+[Full Documentation](https://certbot-dns-dnsimple.readthedocs.io/en/stable/)
- Njalla
+ dnsmadeeasy
-You need to generate an API token inside Settings > API Access or directly at https://njal.la/settings/api/. If you have a static IP-address restrict the access to your IP. I you are not sure, you probably don't have a static IP-address.
+Use of this plugin requires a configuration file containing DNS Made Easy API credentials, obtained from your DNS Made Easy [account page](https://cp.dnsmadeeasy.com/account/info).
-Example configuration:
-
- ```yaml
+```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-njalla
- njalla_token: 0123456789abcdef0123456789abcdef01234567
- ```
+ provider: dns-dnsmadeeasy
+ dnsmadeeasy_api_key: dnsmadeeasy-api-key
+ dnsmadeeasy_secret_key: dnsmadeeasy-secret-key
+```
+
+[Full Documentation](https://certbot-dns-dnsmadeeasy.readthedocs.io/en/stable/)
- TransIP
-
-You will need to generate an API key from the TransIP Control Panel at https://www.transip.nl/cp/account/api/.
+ domainoffensive
-The propagation limit will be automatically raised to 240 seconds.
+Use of this plugin requires an API token, obtained from domainoffensive account page in the menu under **Domains** > **Settings** > **Let's Encrypt API token**.
-Example configuration:
```yaml
email: your.email@example.com
domains:
@@ -572,108 +627,591 @@ Example configuration:
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-transip
- transip_username: transip-user
- transip_api_key: |
- -----BEGIN PRIVATE KEY-----
- MII..ABCDEFGHIJKLMNOPQRSTUVWXYZ
- AAAAAABCDEFGHIJKLMNOPQRSTUVWXYZ
- -----END PRIVATE KEY-----
+ provider: dns-domainoffensive
+ domainoffensive_token: domainoffensive-token
+ ```
+
+[Full Documentation DE](https://www.do.de/wiki/freie-ssl-tls-zertifikate-ueber-acme/)
+
+
+
+
+ DreamHost
+
+Use of this plugin an API key from DreamHost with `dns-*` permissions. You can get it [here](https://panel.dreamhost.com/?tree=home.api)
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-dreamhost
+ dreamhost_api_key: dreamhost-api-key
+ ```
+
+`dreamhost_baseurl` is no longer supported since v6.0.0 and defaults to `https://api.dreamhost.com/`
+
+
+
+
+ DuckDNS
+
+Use of this plugin requires an API token, obtained from the DuckDNS account page.
+
+```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-duckdns
+ duckdns_token: duckdns-token
+
+```
+
+[Full documentation](https://github.com/infinityofspace/certbot_dns_duckdns?tab=readme-ov-file#usage)
+
+
+
+
+ Dynu
+
+You can get the API key in the API Credentials area of the Dynu control panel:
+
+```yaml
+email: your.email@example.com
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-dynu
+ dynu_auth_token: 0123456789abcdef
+```
+
+
+
+
+ easyDNS
+
+easyDNS REST API access must be requested and granted in order to use this module: after logging into your account.
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-easydns
+ easydns_token: 0123456789abcdef
+ easydns_key: ****
+ easydns_endpoint: https://rest.easydns.net
+ ```
+
+
+
+
+ EuroDNS
+
+ You can configure the APP id and the API key in the API Users area of the Eurodns control panel:
+
+```yaml
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-eurodns
+ eurodns_applicationId: X-APP-ID
+ eurodns_apiKey: X-API-KEY
+ propagation_seconds: 60
+```
+
+
+
+
+ Gandi
+
+Use of this plugin requires an [PersonalAccessToken](https://helpdesk.gandi.net/hc/en-us/articles/14051397687324-Personal-Access-Tokens) for the [Gandi LiveDNS API](https://api.gandi.net/docs/livedns/) with `Domains` scope for the `domain.tld` you are going to request a certificate for.
+If you only have an Gandi LiveDNS `API key`, please refer to the [FAQ](https://github.com/obynio/certbot-plugin-gandi?tab=readme-ov-file#faq) on how to use this.
+Due to the wide scope of this `API key`, this is not the recommended setup.
+
+```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-gandi
+ gandi_token: gandi-personalaccesstoken
+```
+
+[Full Documentation](https://github.com/obynio/certbot-plugin-gandi?tab=readme-ov-file)
+
+
+
+
+ gehirn
+
+Use of this plugin requires Gehirn Infrastructure Service DNS API credentials, obtained from your Gehirn Infrastructure Service [dashboard](https://gis.gehirn.jp/).
+
+```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-gehirn
+ gehirn_api_secret: gehirn-api-secret
+ gehirn_api_token: gehirn-api-token
+```
+
+[Full Documentation](https://certbot-dns-gehirn.readthedocs.io/en/stable/)
+
+
+
+
+ GoDaddy
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-godaddy
+ godaddy_secret: YOUR_GODADDY_SECRET
+ godaddy_key: YOUR_GODADDY_KEY
+ ```
+
+To obtain the ACME DNS API Key and Secret, follow the instructions here:
+
+
+**IMPORTANT**: GoDaddy limits DNS API access to customers with 10 or more domains and/or an active "Discount Domain Club – Premier Membership" plan; the API will respond with a HTTP401 otherwise. See the [Terms of Use](https://developer.godaddy.com/getstarted) for more information.
+
+
+
+
+ Google Cloud
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-google
+ google_creds: google.json
+ ```
+
+Please copy your credentials file "google.json" into the "share" shared folder on the Home Assistant host before starting the service.
+
+One way is to use the **Samba** app to make the folder available via network or SSH App.
+
+The credential file can be created and downloaded when creating the service user within the Google cloud.
+You can find additional information regarding the required permissions in the "credentials" section here:
+
+
+
+
+
+
+ Hurricane Electric (HE)
+
+Use of this plugin requires your Hurricane Electric username and password.
+You will need to create the dynamic TXT record from within the dns.he.net interface before you will be able to make updates. You will not be able to dynamically create and delete these TXT records as doing so would subsequently remove your ddns key associated with the record.
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ propagation_seconds: 310
+ provider: dns-he
+ he_user: me
+ he_pass: ******
+ ```
+
+[Full Documentation](https://dns.he.net/)
+
+
+
+
+ Hetzner
+
+Use of this plugin requires a Hetzner Cloud API token. See the Hetzner Docs on [Generating an API token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token/).
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-hetzner
+ hetzner_api_token: hetzner-api-token
+ ```
+
+[Full Documentation](https://github.com/ctrlaltcoop/certbot-dns-hetzner)
+
+
+
+
+ Infomaniak
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-infomaniak
+ infomaniak_api_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ ```
+
+To obtain the DNS API token follow the instructions here:
+
+
+
+Choose "Domain" as the scope.
+
+
+
+
+ INWX
+
+Use the user for the dyndns service, not the normal user.
+The shared secret is the 2FA code, it must be the same length as the example.
+To get this code, you must activate the 2FA or deactivate and reactivate 2FA.
+Without 2FA leave the example key.
+
+Example configuration:
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-inwx
+ inwx_username: user
+ inwx_password: password
+ inwx_shared_secret: ABCDEFGHIJKLMNOPQRSTUVWXYZ012345
+ ```
+
+
+
+
+ IONOS
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-ionos
+ ionos_prefix: YOUR_IONOS_API_KEY_PREFIX
+ ionos_secret: YOUR_IONOS_API_KEY_SECRET
+ ```
+
+To obtain the DNS API Key Information, follow the instructions here:
+
+
+
+
+
+ Joker
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-joker
+ joker_username: username
+ joker_password: password
+ ```
+
+You can find further detailed information here:
+
+
+
+
+
+
+
+ Linode
+
+To use this app with Linode DNS, first [create a new API/access key](https://www.linode.com/docs/platform/api/getting-started-with-the-linode-api#get-an-access-token), with read/write permissions to DNS; no other permissions are needed.
+
+ ```yaml
+ email: you@mailprovider.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-linode
+ linode_key: 865c9f462c7d54abc1ad2dbf79c938bc5c55575fdaa097ead2178ee68365ab3e
+ ```
+
+
+
+
+ Loopia
+
+To use this app with Loopia DNS, first [create a new API user](https://customerzone.loopia.com/api/), with the following minimum required permissions:
+
+- `addZoneRecord` - Required to create DNS records
+- `getZoneRecords` - Required to verify DNS records
+- `removeZoneRecord` - Required to clean up DNS records
+- `removeSubdomain` - Required for complete cleanup
+
+Example configuration in YAML edit mode:
+
+```yaml
+email: you@mailprovider.com
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-loopia
+ loopia_user: example@loopiaapi
+ loopia_password: supersecretpasswordhere
+```
+
+
+
+
+ LuaDNS
+
+Use of this plugin requires LuaDNS API credentials, obtained from your [account settings page](https://api.luadns.com/settings).
+
+```yaml
+email: your.email@example.com
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-luadns
+ luadns_email: your.email@example.com
+ luadns_token: luadns-token
+```
+
+[Full Documentation](https://certbot-dns-luadns.readthedocs.io/en/stable/)
+
+
+
+
+ mijn.host
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-mijn-host
+ mijn_host_api_key: XXXXXX
+ propagation_seconds: 60
+ ```
+
+The `mijn_host_api_key` is the account's API key.
+The API key assigned to your mijn.host account can be found in your mijn.host Control panel.
+
+
+
+
+ Namecheap
+
+To use this app with Namecheap, you must first enable API access on your account. See "Enabling API Access" and "Whitelisting IP" [here](https://www.namecheap.com/support/api/intro/) for details and requirements.
+
+Example configuration:
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-namecheap
+ namecheap_username: your-namecheap-username
+ namecheap_api_key: 0123456789abcdef0123456789abcdef01234567
+ ```
+
+
+
+
+ Netcup
+
+Both the API password and key can be obtained via the following page:
+It is important to set the `propagation_seconds` to >= 630 seconds due to the slow DNS update of Netcup.
+
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-netcup
+ netcup_customer_id: "userid"
+ netcup_api_key: ****
+ netcup_api_password: ****
+ propagation_seconds: "900"
```
+References:
+
+-
+-
+
- OVH
+ Njalla
-You will need to generate an OVH API Key first at https://eu.api.ovh.com/createToken/ (for Europe) or https://ca.api.ovh.com/createToken/ (for north America).
+You need to generate an API token inside Settings > API Access or directly at . If you have a static IP-address restrict the access to your IP. I you are not sure, you probably don't have a static IP-address.
-When creating the API Key, you must ensure that the following rights are granted:
-* ``GET /domain/zone/*``
-* ``PUT /domain/zone/*``
-* ``POST /domain/zone/*``
-* ``DELETE /domain/zone/*``
+Example configuration:
-Example configuration
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-ovh
- ovh_endpoint: ovh-eu
- ovh_application_key: 0123456789abcdef0123456789abcdef01234
- ovh_application_secret: 0123456789abcdef0123456789abcdef01234
- ovh_consumer_key: 0123456789abcdef0123456789abcdef01234
+ provider: dns-njalla
+ njalla_token: 0123456789abcdef0123456789abcdef01234567
```
-Use `ovh_endpoint: ovh-ca` for north America region.
- RFC2136
-
-You will need to set up a server with RFC2136 (Dynamic Update) support with a TKEY (to authenticate the updates). How to do this will vary depending on the DNS server software in use. For Bind9, you first need to first generate an authentication key by running
+ noris network
- ```
- $ tsig-keygen -a hmac-sha512 letsencrypt
- key "letsencrypt" {
- algorithm hmac-sha512;
- secret "G/adDW8hh7FDlZq5ZDW3JjpU/I7DzzU1PDvp26DvPQWMLg/LfM2apEOejbfdp5BXu78v/ruWbFvSK5dwYY7bIw==";
- };
+ ```yaml
+ email: your.email@example.com
+ domains:
+ - your.domain.tld
+ certfile: fullchain.pem
+ keyfile: privkey.pem
+ challenge: dns
+ dns:
+ provider: dns-noris
+ noris_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ propagation_seconds: 240
```
-You don't need to publish this; just copy the key data into your named.conf file:
- ```
-
- key "letsencrypt" {
- algorithm hmac-sha512;
- secret "G/adDW8hh7FDlZq5ZDW3JjpU/I7DzzU1PDvp26DvPQWMLg/LfM2apEOejbfdp5BXu78v/ruWbFvSK5dwYY7bIw==";
- };
-
- ```
-And ensure you have an update policy in place in the zone that uses this key to enable update of the correct domain (which must match the domain in your yaml configuration):
- ```
-
- update-policy {
- grant letsencrypt name _acme-challenge.home-assistant.io. txt;
- };
- ```
+To obtain the `noris_token` follow the instructions as described in our [GitHub repository][GitHub repo].
-For this provider, you will need to supply all the `rfc2136_*` options. Note that the `rfc2136_port` item is required (there is no default port in the add-on) and, most importantly, the port number must be quoted. Also, be sure to copy in the key so certbot can authenticate to the DNS server. Finally, the algorithm should be in all caps.
+You can define the `propagation_seconds` explicitly. Otherwise, it will use the default value (currently set to `60` seconds).
-An example configuration:
+[GitHub repo]:
+
+
+
+
+ nsone
+
+Use of this plugin requires NS1 API credentials, obtained from your NS1 [account page](https://my.nsone.net/#/account/settings).
+
+```yaml
+email: your.email@example.com
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-nsone
+ nsone_api_key: nsone-api-key
+```
+
+[Full Documentation](https://certbot-dns-nsone.readthedocs.io/en/stable/)
+
+
+
+
+ OVH
+
+You will need to generate an OVH API Key first at (for Europe) or (for North America).
+Further documentation is [here](https://certbot-dns-ovh.readthedocs.io/en/stable/).
+
+When creating the API Key, you must ensure that the following rights are granted:
+
+- ``GET /domain/zone/*``
+- ``PUT /domain/zone/*``
+- ``POST /domain/zone/*``
+- ``DELETE /domain/zone/*``
+
+Example configuration
```yaml
email: your.email@example.com
domains:
- - home-assistant.io
+ - your.domain.tld
certfile: fullchain.pem
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-rfc2136
- rfc2136_server: dns-server.dom.ain
- rfc2136_port: '53'
- rfc2136_name: letsencrypt
- rfc2136_secret: "secret-key"
- rfc2136_algorithm: HMAC-SHA512
+ provider: dns-ovh
+ ovh_endpoint: ovh-eu
+ ovh_application_key: 0123456789abcdef0123456789abcdef01234
+ ovh_application_secret: 0123456789abcdef0123456789abcdef01234
+ ovh_consumer_key: 0123456789abcdef0123456789abcdef01234
```
+Use `ovh_endpoint: ovh-ca` for North America region.
+
- INWX
-
-Use the user for the dyndns service, not the normal user.
-The shared secret is the 2FA code, it must be the same length as the example.
-To get this code, you must activate the 2FA or deactivate and reactivate 2FA.
-Without 2FA leave the example key.
+ Plesk Hosting
-Example configuration:
```yaml
email: your.email@example.com
domains:
@@ -682,12 +1220,20 @@ Example configuration:
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-inwx
- inwx_username: user
- inwx_password: password
- inwx_shared_secret: ABCDEFGHIJKLMNOPQRSTUVWXYZ012345
+ provider: dns-plesk
+ plesk_username: your-username
+ plesk_password: your-password
+ plesk_api_url: https://plesk.example.com
+ propagation_seconds: 120
```
+The `plesk_username` and `plesk_password` are the same as those you use on the login page of your admin panel.
+
+The `plesk_api_url` is the base URL of your Plesk admin panel.
+
+You can define the `propagation_seconds` explicitly. Otherwise, it will use a custom default value (currently set to `120` seconds).
+If the provided value is less than `120`, then the value is forced to a minimum of `120` seconds.
+
@@ -710,9 +1256,42 @@ dns:
porkbun_key: 0123456789abcdef0123456789abcdef01234
porkbun_secret: 0123456789abcdef0123456789abcdef01234
```
+
+
- Dreamhost
+ RFC2136
+
+You will need to set up a server with RFC2136 (Dynamic Update) support with a TKEY (to authenticate the updates). How to do this will vary depending on the DNS server software in use. For Bind9, you first need to first generate an authentication key by running
+
+ ```shell
+ $ tsig-keygen -a hmac-sha512 letsencrypt
+ key "letsencrypt" {
+ algorithm hmac-sha512;
+ secret "xxxxxxxxxxxxxxxxxx==";
+ };
+ ```
+
+You don't need to publish this; just copy the key data into your named.conf file:
+
+ ```shell
+ key "letsencrypt" {
+ algorithm hmac-sha512;
+ secret "xxxxxxxxxxxxxxxxxx==";
+ };
+ ```
+
+And ensure you have an update policy in place in the zone that uses this key to enable update of the correct domain (which must match the domain in your yaml configuration):
+
+ ```shell
+ update-policy {
+ grant letsencrypt name _acme-challenge.your.domain.tld. txt;
+ };
+ ```
+
+For this provider, you will need to supply all the `rfc2136_*` options. Note that the `rfc2136_port` item is required (there is no default port in the app) and, most importantly, the port number must be quoted. Also, be sure to copy in the key so certbot can authenticate to the DNS server. Finally, the algorithm should be in all caps.
+
+An example configuration:
```yaml
email: your.email@example.com
@@ -722,15 +1301,18 @@ dns:
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-dreamhost
- dreamhost_baseurl: https://api.dreamhost.com/
- dreamhost_api_key: XXXXXX
+ provider: dns-rfc2136
+ rfc2136_server: dns-server.dom.ain
+ rfc2136_port: '53'
+ rfc2136_name: letsencrypt
+ rfc2136_secret: "secret-key"
+ rfc2136_algorithm: HMAC-SHA512
```
+
+
- ClouDNS
-In order to use a domain with this challenge, you first need to log into your control panel and create a
-new HTTP API user from the "API & Resellers" page on top of your control panel.
+ route53
```yaml
email: your.email@example.com
@@ -740,39 +1322,67 @@ new HTTP API user from the "API & Resellers" page on top of your control panel.
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-cloudns
- cloudns_auth_id: 12345
- cloudns_auth_password: ******
+ provider: dns-route53
+ aws_access_key_id: 0123456789ABCDEF0123
+ aws_secret_access_key: 0123456789abcdef0123456789/abcdef0123456
```
-API Users have full account access. It is recommended to create an API Sub-user, which can be limited in scope. You can use either the `sub-auth-id` or the `sub-auth-user` as follows:
- ```yaml
- email: your.email@example.com
- domains:
- - your.domain.tld
- certfile: fullchain.pem
- keyfile: privkey.pem
- challenge: dns
- dns:
- provider: dns-cloudns
- cloudns_sub_auth_id: 12345
- cloudns_auth_password: ******
- ```
- ```yaml
- email: your.email@example.com
- domains:
- - your.domain.tld
- certfile: fullchain.pem
- keyfile: privkey.pem
- challenge: dns
- dns:
- provider: dns-cloudns
- cloudns_sub_auth_user: alice
- cloudns_auth_password: ******
+The configuration also takes `aws_region` which defaults to `us-east-1` (Route 53 is a global AWS service). Set it only if you need to use a different region endpoint.
+
+For security reasons, don't use your main account's credentials. Instead, add a new [AWS user](https://console.aws.amazon.com/iam/home?#/users) with _Access Type: Programmatic access_ and use that user's access key. Assign a minimum [policy](https://console.aws.amazon.com/iam/home?#/policies$new?step=edit) like the following example. Make sure to replace the Resource ARN in the first statement to your domain's hosted zone ARN or use _*_ for all.
+
+ ```json
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "ChangeSpecificDomainsRecordSet",
+ "Effect": "Allow",
+ "Action": "route53:ChangeResourceRecordSets",
+ "Resource": "arn:aws:route53:::hostedzone/01234567890ABC"
+ },
+ {
+ "Sid": "ListAllHostedZones",
+ "Effect": "Allow",
+ "Action": "route53:ListHostedZones",
+ "Resource": "*"
+ },
+ {
+ "Sid": "ReadChanges",
+ "Effect": "Allow",
+ "Action": "route53:GetChange",
+ "Resource": "arn:aws:route53:::change/*"
+ }
+ ]
+ }
```
+
+
- Hurricane Electric (HE)
+ SakuraCloud
+
+Use of this plugin requires Sakura Cloud DNS API credentials, obtained from your Sakura Cloud DNS [apikey page](https://secure.sakura.ad.jp/cloud/#!/apikey/top/).
+
+```yaml
+email: your.email@example.com
+domains:
+ - your.domain.tld
+certfile: fullchain.pem
+keyfile: privkey.pem
+challenge: dns
+dns:
+ provider: dns-sakuracloud
+ sakuracloud_api_secret: ''
+ sakuracloud_api_token: ''
+```
+
+[Full Documentation](https://certbot-dns-sakuracloud.readthedocs.io/en/stable/)
+
+
+
+
+ Simply.com
```yaml
email: your.email@example.com
@@ -782,17 +1392,24 @@ API Users have full account access. It is recommended to create an API Sub-user
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-he
- he_user: me
- he_pass: ******
+ provider: dns-simply
+ simply_account_name: Sxxxxxx
+ simply_api_key: YOUR_API_KEY # Replace 'YOUR_API_KEY' with your actual Simply.com API key.
```
+
+The `simply_account_name` refers to the Simply.com account number (Sxxxxxx), and the `simply_api_key` is the account's API key.
+The API key assigned to your Simply.com account can be found in your Simply.com Control panel.
+
- Netcup
+ TransIP
+
+You will need to generate an API key from the TransIP Control Panel at .
-Both the API password and key can be obtained via the following page: https://www.customercontrolpanel.de/daten_aendern.php?sprung=api
-It is important to set the propagation_seconds to >= 630 seconds due to the slow DNS update of Netcup.
+The propagation limit will be automatically raised to 240 seconds.
+
+Example configuration:
```yaml
email: your.email@example.com
@@ -802,21 +1419,21 @@ It is important to set the propagation_seconds to >= 630 seconds due to the slow
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-netcup
- netcup_customer_id: "userid"
- netcup_api_key: ****
- netcup_api_password: ****
- propagation_seconds: "900"
+ provider: dns-transip
+ transip_username: transip-user
+ transip_api_key: |
+ -----BEGIN PRIVATE KEY-----
+ MII..ABCDEFGHIJKLMNOPQRSTUVWXYZ
+ AAAAAABCDEFGHIJKLMNOPQRSTUVWXYZ
+ -----END PRIVATE KEY-----
```
-References:
-* https://helpcenter.netcup.com/de/wiki/general/unsere-api#authentifizierung
-* https://github.com/coldfix/certbot-dns-netcup/issues/28
+
- easyDNS
+ WebSupport
-easyDNS REST API access must be requested and granted in order to use this module: https://cp.easydns.com/manage/security/api/signup.php after logging into your account.
+An identifier and secret key have to be obtained to use this module (see ).
```yaml
email: your.email@example.com
@@ -826,53 +1443,66 @@ easyDNS REST API access must be requested and granted in order to use this modul
keyfile: privkey.pem
challenge: dns
dns:
- provider: dns-easydns
- easydns_token: 0123456789abcdef
- easydns_key: ****
- easydns_endpoint: https://rest.easydns.net
+ provider: dns-websupport
+ websupport_identifier:
+ websupport_secret_key:
```
-
+
## Certificate files
The certificate files will be available within the "ssl" share after successful request of the certificates.
-By default other addons are referring to the correct path of the certificates.
-You can in addition find the files via the "samba" addon within the "ssl" share.
+By default other apps are referring to the correct path of the certificates.
+You can in addition find the files via the **Samba** app within the "ssl" share.
## Supported DNS providers
```txt
+dns-lego (generic, supports any lego DNS provider)
dns-azure
-dns-cloudns
dns-cloudflare
+dns-cloudns
dns-desec
dns-digitalocean
dns-directadmin
dns-dnsimple
dns-dnsmadeeasy
-dns-duckdns
+dns-domainoffensive
dns-dreamhost
+dns-duckdns
+dns-dynu
+dns-easydns
+dns-eurodns
+dns-gandi
dns-gehirn
+dns-godaddy
dns-google
+dns-he
dns-hetzner
dns-infomaniak
+dns-inwx
+dns-ionos
+dns-joker
dns-linode
+dns-loopia
dns-luadns
+dns-mijn-host
+dns-namecheap
+dns-netcup
dns-njalla
+dns-noris
dns-nsone
dns-ovh
+dns-plesk
+dns-porkbun
dns-rfc2136
dns-route53
dns-sakuracloud
-dns-namecheap
-dns-netcup
-dns-gandi
+dns-simply
dns-transip
-dns-inwx
-dns-porkbun
-dns-easydns
+dns-websupport
```
## Support
diff --git a/letsencrypt/Dockerfile b/letsencrypt/Dockerfile
index 9e2d833a20a..05f55466030 100644
--- a/letsencrypt/Dockerfile
+++ b/letsencrypt/Dockerfile
@@ -1,80 +1,61 @@
ARG BUILD_FROM
FROM $BUILD_FROM
+# Allow pip to install packages system-wide on Debian
+ENV PIP_BREAK_SYSTEM_PACKAGES=1
+
# setup base
+# certbot-dns-multi replaces most individual DNS plugins using lego
+# Only legacy plugins are kept for providers not supported by lego: gehirn, eurodns, noris
+# Azure and HE is also kept as legacy for backward compatibility (will be removed in future version)
ARG \
BUILD_ARCH \
- CRYPTOGRAPHY_VERSION \
- CERTBOT_VERSION \
+ ACME_VERSION \
CERTBOT_DNS_AZURE_VERSION \
- CERTBOT_DNS_CLOUDNS_VERSION \
- CERTBOT_DNS_DESEC_VERSION \
- CERTBOT_DNS_DIRECTADMIN_VERSION \
- CERTBOT_DNS_DREAMHOST_VERSION \
- CERTBOT_DNS_DUCKDNS_VERSION \
- CERTBOT_DNS_EASYDNS_VERSION \
- CERTBOT_DNS_GOOGLE_DOMAINS_VERSION \
- CERTBOT_DNS_HE_VERSION \
- CERTBOT_DNS_HETZNER_VERSION \
- CERTBOT_DNS_INFOMANIAK_VERSION \
- CERTBOT_DNS_INWX_VERSION \
- CERTBOT_DNS_NAMECHEAP_VERSION \
- CERTBOT_DNS_TRANSIP_VERSION \
- CERTBOT_DNS_PORKBUN_VERSION \
- CERTBOT_NETCUP_VERSION \
- CERTBOT_NJALLA_VERSION \
- CERTBOT_GANDI_VERSION \
- ACME_VERSION
+ CERTBOT_DNS_EURODNS_VERSION \
+ CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION \
+ CERTBOT_DNS_MULTI_VERSION \
+ CERTBOT_DNS_NORISNETWORK_VERSION \
+ CERTBOT_VERSION \
+ CRYPTOGRAPHY_VERSION
RUN \
set -x \
- && apk add --no-cache --update \
- libffi \
- musl \
- openssl \
- && apk add --no-cache --virtual .build-dependencies \
- build-base \
- libffi-dev \
- musl-dev \
- openssl-dev \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ build-essential \
+ ca-certificates \
cargo \
- && pip3 install --no-cache-dir --find-links \
- "https://wheels.home-assistant.io/alpine-$(cut -d '.' -f 1-2 < /etc/alpine-release)/${BUILD_ARCH}/" \
- cryptography==${CRYPTOGRAPHY_VERSION} \
+ golang \
+ libffi8 \
+ libffi-dev \
+ libssl-dev \
+ openssl \
+ python3 \
+ python3-dev \
+ python3-pip \
+ rustc \
+ && pip3 install --no-cache-dir \
+ acme==${ACME_VERSION} \
certbot==${CERTBOT_VERSION} \
certbot-dns-azure==${CERTBOT_DNS_AZURE_VERSION} \
- certbot-dns-cloudflare==${CERTBOT_VERSION} \
- certbot-dns-cloudns==${CERTBOT_DNS_CLOUDNS_VERSION} \
- certbot-dns-desec==${CERTBOT_DNS_DESEC_VERSION} \
- certbot-dns-digitalocean==${CERTBOT_VERSION} \
- certbot-dns-directadmin==${CERTBOT_DNS_DIRECTADMIN_VERSION} \
- certbot-dns-dnsimple==${CERTBOT_VERSION} \
- certbot-dns-dnsmadeeasy==${CERTBOT_VERSION} \
- certbot-dns-duckdns==${CERTBOT_DNS_DUCKDNS_VERSION} \
+ certbot-dns-eurodns==${CERTBOT_DNS_EURODNS_VERSION} \
certbot-dns-gehirn==${CERTBOT_VERSION} \
- certbot-dns-google==${CERTBOT_VERSION} \
- certbot-dns-google-domains==${CERTBOT_DNS_GOOGLE_DOMAINS_VERSION} \
- certbot-dns-hetzner==${CERTBOT_DNS_HETZNER_VERSION} \
- certbot-dns-infomaniak==${CERTBOT_DNS_INFOMANIAK_VERSION} \
- certbot-dns-linode==${CERTBOT_VERSION} \
- certbot-dns-luadns==${CERTBOT_VERSION} \
- certbot-dns-njalla==${CERTBOT_NJALLA_VERSION} \
- certbot-dns-nsone==${CERTBOT_VERSION} \
- certbot-dns-porkbun==${CERTBOT_DNS_PORKBUN_VERSION} \
- certbot-dns-ovh==${CERTBOT_VERSION} \
- certbot-dns-rfc2136==${CERTBOT_VERSION} \
- certbot-dns-route53==${CERTBOT_VERSION} \
- certbot-dns-sakuracloud==${CERTBOT_VERSION} \
- certbot-dns-namecheap==${CERTBOT_DNS_NAMECHEAP_VERSION} \
- certbot-dns-netcup==${CERTBOT_NETCUP_VERSION} \
- certbot-plugin-gandi==${CERTBOT_GANDI_VERSION} \
- certbot-dns-transip==${CERTBOT_DNS_TRANSIP_VERSION} \
- certbot-dns-inwx==${CERTBOT_DNS_INWX_VERSION} \
- certbot-dns-dreamhost==${CERTBOT_DNS_DREAMHOST_VERSION} \
- certbot-dns-he==${CERTBOT_DNS_HE_VERSION} \
- certbot-dns-easydns==${CERTBOT_DNS_EASYDNS_VERSION} \
- acme==${ACME_VERSION} \
- && apk del .build-dependencies
+ certbot-dns-hurricane-electric==${CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION} \
+ certbot-dns-multi==${CERTBOT_DNS_MULTI_VERSION} \
+ certbot-dns-norisnetwork==${CERTBOT_DNS_NORISNETWORK_VERSION} \
+ cryptography==${CRYPTOGRAPHY_VERSION} \
+ && apt-get purge -y --auto-remove \
+ build-essential \
+ cargo \
+ golang \
+ libffi-dev \
+ libssl-dev \
+ python3-dev \
+ python3-pip \
+ rustc \
+ && rm -rf /var/lib/apt/lists/* \
+ && rm -rf /root/.cache
# Copy data
COPY rootfs /
diff --git a/letsencrypt/README.md b/letsencrypt/README.md
index 66dfc36fcfe..83b361d8769 100644
--- a/letsencrypt/README.md
+++ b/letsencrypt/README.md
@@ -1,22 +1,13 @@
-# Home Assistant Add-on: Letsencrypt
+# Home Assistant App: Letsencrypt
Let's Encrypt is a certificate authority that provides free X.509 certificates for Transport Layer Security encryption via an automated process designed to eliminate the hitherto complex process of manual creation, validation, signing, installation, and renewal of certificates for secure websites.
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
Setting up Letsencrypt allows you to use validated certificates for your webpages and web-interfaces.
It requires you to own the domain you are requesting the certificate for.
The generated certificate can be used within others addons. By default the path and file for the certificates within other addons will refer to the files generated within this addon.
-[discord]: https://discord.gg/c5DvZ4e
-[forum]: https://community.home-assistant.io
-[issue]: https://github.com/home-assistant/hassio-addons/issues
-[certbot]: https://certbot.eff.org
-[reddit]: https://reddit.com/r/homeassistant
-
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
diff --git a/letsencrypt/build.yaml b/letsencrypt/build.yaml
index 07f8960ca3f..2d910de1f84 100644
--- a/letsencrypt/build.yaml
+++ b/letsencrypt/build.yaml
@@ -1,32 +1,18 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.18
- amd64: ghcr.io/home-assistant/amd64-base-python:3.11-alpine3.18
- armhf: ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.18
- armv7: ghcr.io/home-assistant/armv7-base-python:3.11-alpine3.18
- i386: ghcr.io/home-assistant/i386-base-python:3.11-alpine3.18
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:trixie-2025.12.2
+ amd64: ghcr.io/home-assistant/amd64-base-debian:trixie-2025.12.2
args:
- CRYPTOGRAPHY_VERSION: 41.0.5
- CERTBOT_DNS_AZURE_VERSION: 2.4.0
- CERTBOT_DNS_CLOUDNS_VERSION: 0.6.0
- CERTBOT_DNS_DESEC_VERSION: 1.2.1
- CERTBOT_DNS_DIRECTADMIN_VERSION: 1.0.3
- CERTBOT_DNS_DUCKDNS_VERSION: 1.3
- CERTBOT_DNS_EASYDNS_VERSION: 0.1.2
- CERTBOT_DNS_HE_VERSION: 1.0.0
- CERTBOT_DNS_HETZNER_VERSION: 2.0.0
- CERTBOT_DNS_INFOMANIAK_VERSION: 0.2.1
- CERTBOT_DNS_INWX_VERSION: 2.2.0
- CERTBOT_DNS_NAMECHEAP_VERSION: 1.0.0
- CERTBOT_DNS_GOOGLE_DOMAINS_VERSION: 0.1.11
- CERTBOT_DNS_TRANSIP_VERSION: 0.5.2
- CERTBOT_DNS_PORKBUN_VERSION: 0.8.0
- CERTBOT_GANDI_VERSION: 1.5.0
- CERTBOT_NETCUP_VERSION: 1.4.3
- CERTBOT_NJALLA_VERSION: 1.0.0
- CERTBOT_VERSION: 2.7.4
- CERTBOT_DNS_DREAMHOST_VERSION: 1.0
- ACME_VERSION: 2.7.4
+ ACME_VERSION: 3.3.0
+ # certbot-dns-multi replaces most individual DNS plugins using lego
+ CERTBOT_DNS_MULTI_VERSION: 4.30.1
+ # Only legacy plugins are kept for providers not supported by lego:
+ # gehirn, eurodns, noris
+ CERTBOT_DNS_EURODNS_VERSION: 1.8.1
+ CERTBOT_DNS_NORISNETWORK_VERSION: 0.3.0
+ # Azure and HE kept as legacy for backward compatibility
+ # (provider supported by lego, will be removed in future version)
+ CERTBOT_DNS_AZURE_VERSION: 2.6.1
+ CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION: 0.1.0
+ CERTBOT_VERSION: 3.3.0
+ CRYPTOGRAPHY_VERSION: 44.0.2
diff --git a/letsencrypt/config.yaml b/letsencrypt/config.yaml
index bbb3fb74a18..0f6e7eb8851 100644
--- a/letsencrypt/config.yaml
+++ b/letsencrypt/config.yaml
@@ -1,15 +1,13 @@
---
-version: 5.0.15
+version: 6.0.4
+breaking_versions: [5.3.0, 6.0.0]
slug: letsencrypt
name: Let's Encrypt
description: Manage certificate from Let's Encrypt
url: https://github.com/home-assistant/addons/tree/master/letsencrypt
arch:
- - armhf
- - armv7
- aarch64
- amd64
- - i386
boot: manual
image: homeassistant/{arch}-addon-letsencrypt
init: false
@@ -17,9 +15,6 @@ map:
- ssl:rw
- share
options:
- domains:
- - null
- email: null
keyfile: privkey.pem
certfile: fullchain.pem
challenge: http
@@ -33,21 +28,23 @@ schema:
keyfile: str
certfile: str
challenge: list(dns|http)
- acme_root_ca_cert: str?
- acme_server: url?
- key_type: list(ecdsa|rsa)?
- elliptic_curve: list(secp256r1|secp384r1)?
dns:
+ # Note: When configuring DNS in the UI, only copy the attributes below this
+ # line (e.g., 'provider: dns-cloudflare', 'cloudflare_email: ...') into the
+ # "DNS Provider configuration" field. Do NOT include the 'dns:' key itself.
+ # Developer note: please add a new plugin alphabetically into all lists
aws_access_key_id: str?
+ aws_region: str?
aws_secret_access_key: str?
azure_config: str?
cloudflare_api_key: str?
cloudflare_api_token: str?
cloudflare_email: email?
cloudns_auth_id: int?
+ cloudns_auth_password: str?
cloudns_sub_auth_id: int?
+ # Invalid since v6.0.0, will be completely removed later
cloudns_sub_auth_user: str?
- cloudns_auth_password: str?
desec_token: str?
digitalocean_token: str?
directadmin_password: str?
@@ -56,58 +53,138 @@ schema:
dnsimple_token: str?
dnsmadeeasy_api_key: str?
dnsmadeeasy_secret_key: str?
+ domainoffensive_token: str?
+ dreamhost_api_key: str?
+ # Invalid since v6.0.0, will be completely removed later
+ dreamhost_baseurl: str?
duckdns_token: str?
+ dynu_auth_token: str?
+ easydns_endpoint: str?
+ easydns_key: str?
+ easydns_token: str?
+ eurodns_apiKey: str?
+ eurodns_applicationId: str?
gandi_api_key: str?
+ # Invalid since v6.0.0, will be completely removed later
gandi_sharing_id: str?
+ gandi_token: str?
gehirn_api_secret: str?
gehirn_api_token: str?
+ godaddy_key: str?
+ godaddy_secret: str?
google_creds: str?
- google_domains_access_token: str?
- google_domains_zone: str?
+ he_pass: str?
+ he_user: str?
hetzner_api_token: str?
infomaniak_api_token: str?
+ inwx_password: str?
+ inwx_shared_secret: str?
+ inwx_username: str?
+ # Invalid since v6.0.0, will be completely removed later
+ ionos_endpoint: str?
+ ionos_prefix: str?
+ ionos_secret: str?
+ # Invalid since v6.0.0, will be completely removed later
+ joker_domain: str?
+ joker_password: str?
+ joker_username: str?
+ lego_env:
+ - str?
+ lego_provider: str?
linode_key: str?
+ # Invalid since v6.0.0, will be completely removed later
linode_version: str?
+ loopia_password: str?
+ loopia_user: str?
luadns_email: email?
luadns_token: str?
- namecheap_username: str?
+ mijn_host_api_key: str?
namecheap_api_key: str?
+ namecheap_username: str?
netcup_api_key: str?
netcup_api_password: str?
netcup_customer_id: str?
njalla_token: str?
+ noris_token: str?
nsone_api_key: str?
- porkbun_key: str?
- porkbun_secret: str?
ovh_application_key: str?
ovh_application_secret: str?
ovh_consumer_key: str?
ovh_endpoint: str?
+ plesk_api_url: str?
+ plesk_password: str?
+ plesk_username: str?
+ porkbun_key: str?
+ porkbun_secret: str?
propagation_seconds: int(60,3600)?
- provider: "list(dns-azure|dns-cloudflare|dns-cloudns|dns-desec|\
- dns-digitalocean|dns-directadmin|dns-dnsimple|dns-dnsmadeeasy|\
- dns-duckdns|dns-gehirn|dns-google|dns-google-domains|\
- dns-hetzner|dns-infomaniak|dns-linode|dns-luadns|dns-njalla|dns-nsone|\
- dns-porkbun|dns-ovh|dns-rfc2136|dns-route53|dns-sakuracloud|\
- dns-namecheap|dns-netcup|dns-gandi|dns-transip|dns-inwx|dns-dreamhost|\
- dns-he|dns-easydns)?"
+ provider: "list(\
+ dns-azure|\
+ dns-cloudflare|\
+ dns-cloudns|\
+ dns-desec|\
+ dns-digitalocean|\
+ dns-directadmin|\
+ dns-dnsimple|\
+ dns-dnsmadeeasy|\
+ dns-domainoffensive|\
+ dns-dreamhost|\
+ dns-duckdns|\
+ dns-dynu|\
+ dns-easydns|\
+ dns-eurodns|\
+ dns-gandi|\
+ dns-gehirn|\
+ dns-godaddy|\
+ dns-google|\
+ dns-he|\
+ dns-hetzner|\
+ dns-infomaniak|\
+ dns-inwx|\
+ dns-ionos|\
+ dns-joker|\
+ dns-lego|\
+ dns-linode|\
+ dns-loopia|\
+ dns-luadns|\
+ dns-mijn-host|\
+ dns-namecheap|\
+ dns-netcup|\
+ dns-njalla|\
+ dns-noris|\
+ dns-nsone|\
+ dns-ovh|\
+ dns-plesk|\
+ dns-porkbun|\
+ dns-rfc2136|\
+ dns-route53|\
+ dns-sakuracloud|\
+ dns-simply|\
+ dns-transip|\
+ dns-websupport)?"
rfc2136_algorithm: str?
rfc2136_name: str?
rfc2136_port: str?
rfc2136_secret: str?
rfc2136_server: str?
+ # Invalid since v6.0.0, will be completely removed later
+ rfc2136_sign_query: bool?
sakuracloud_api_secret: str?
sakuracloud_api_token: str?
+ simply_account_name: str?
+ simply_api_key: str?
transip_api_key: str?
+ # Invalid since v6.0.0, will be completely removed later
+ transip_global_key: list(yes|no)?
transip_username: str?
- inwx_username: str?
- inwx_password: str?
- inwx_shared_secret: str?
- dreamhost_api_key: str?
- dreamhost_baseurl: str?
- he_user: str?
- he_pass: str?
- easydns_endpoint: str?
- easydns_key: str?
- easydns_token: str?
+ websupport_identifier: str?
+ websupport_secret_key: str?
+ key_type: list(ecdsa|rsa)?
+ elliptic_curve: list(secp256r1|secp384r1)?
+ acme_server: url?
+ acme_root_ca_cert: str?
+ verbose: bool?
+ dry_run: bool?
+ test_cert: bool?
+ eab_kid: str?
+ eab_hmac_key: str?
startup: once
diff --git a/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh b/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh
index 2469a197331..61d790b8687 100755
--- a/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh
+++ b/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh
@@ -1,101 +1,110 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Init folder & structures
# ==============================================================================
mkdir -p /data/workdir
mkdir -p /data/letsencrypt
-# Setup Let's encrypt config
-echo -e "dns_desec_token = $(bashio::config 'dns.desec_token')\n" \
- "dns_digitalocean_token = $(bashio::config 'dns.digitalocean_token')\n" \
- "dns_directadmin_url = $(bashio::config 'dns.directadmin_url')\n" \
- "dns_directadmin_username = $(bashio::config 'dns.directadmin_username')\n" \
- "dns_directadmin_password = $(bashio::config 'dns.directadmin_password')\n" \
- "dns_dnsimple_token = $(bashio::config 'dns.dnsimple_token')\n" \
- "dns_dnsmadeeasy_api_key = $(bashio::config 'dns.dnsmadeeasy_api_key')\n" \
- "dns_dnsmadeeasy_secret_key = $(bashio::config 'dns.dnsmadeeasy_secret_key')\n" \
- "dns_duckdns_token = $(bashio::config 'dns.duckdns_token')\n" \
- "dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')\n" \
- "dns_gehirn_api_secret = $(bashio::config 'dns.gehirn_api_secret')\n" \
- "dns_hetzner_api_token = $(bashio::config 'dns.hetzner_api_token')\n" \
- "dns_infomaniak_token = $(bashio::config 'dns.infomaniak_api_token')\n" \
- "dns_linode_key = $(bashio::config 'dns.linode_key')\n" \
- "dns_linode_version = $(bashio::config 'dns.linode_version')\n" \
- "dns_luadns_email = $(bashio::config 'dns.luadns_email')\n" \
- "dns_luadns_token = $(bashio::config 'dns.luadns_token')\n" \
- "dns_namecheap_username = $(bashio::config 'dns.namecheap_username')\n" \
- "dns_namecheap_api_key = $(bashio::config 'dns.namecheap_api_key')\n" \
- "dns_netcup_customer_id = $(bashio::config 'dns.netcup_customer_id')\n" \
- "dns_netcup_api_key = $(bashio::config 'dns.netcup_api_key')\n" \
- "dns_netcup_api_password = $(bashio::config 'dns.netcup_api_password')\n" \
- "dns_njalla_token = $(bashio::config 'dns.njalla_token')\n" \
- "dns_nsone_api_key = $(bashio::config 'dns.nsone_api_key')\n" \
- "dns_porkbun_key = $(bashio::config 'dns.porkbun_key')\n" \
- "dns_porkbun_secret = $(bashio::config 'dns.porkbun_secret')\n" \
- "dns_ovh_endpoint = $(bashio::config 'dns.ovh_endpoint')\n" \
- "dns_ovh_application_key = $(bashio::config 'dns.ovh_application_key')\n" \
- "dns_ovh_application_secret = $(bashio::config 'dns.ovh_application_secret')\n" \
- "dns_ovh_consumer_key = $(bashio::config 'dns.ovh_consumer_key')\n" \
- "dns_rfc2136_server = $(bashio::config 'dns.rfc2136_server')\n" \
- "dns_rfc2136_port = $(bashio::config 'dns.rfc2136_port')\n" \
- "dns_rfc2136_name = $(bashio::config 'dns.rfc2136_name')\n" \
- "dns_rfc2136_secret = $(bashio::config 'dns.rfc2136_secret')\n" \
- "dns_rfc2136_algorithm = $(bashio::config 'dns.rfc2136_algorithm')\n" \
- "aws_access_key_id = $(bashio::config 'dns.aws_access_key_id')\n" \
- "aws_secret_access_key = $(bashio::config 'dns.aws_secret_access_key')\n" \
- "dns_sakuracloud_api_token = $(bashio::config 'dns.sakuracloud_api_token')\n" \
- "dns_sakuracloud_api_secret = $(bashio::config 'dns.sakuracloud_api_secret')\n" \
- "dns_gandi_api_key = $(bashio::config 'dns.gandi_api_key')\n" \
- "dns_transip_username = $(bashio::config 'dns.transip_username')\n" \
- "dns_transip_key_file = /data/transip-rsa.key\n" \
- "dns_inwx_url = https://api.domrobot.com/xmlrpc/\n" \
- "dns_inwx_username = $(bashio::config 'dns.inwx_username')\n" \
- "dns_inwx_password = $(bashio::config 'dns.inwx_password')\n" \
- "dns_inwx_shared_secret = $(bashio::config 'dns.inwx_shared_secret')\n" \
- "dns_google_domains_access_token = $(bashio::config 'dns.google_domains_access_token')\n" \
- "dns_cloudns_auth_password = $(bashio::config 'dns.cloudns_auth_password')\n" \
- "dns_dreamhost_baseurl = $(bashio::config 'dns.dreamhost_baseurl')\n" \
- "dns_dreamhost_api_key = $(bashio::config 'dns.dreamhost_api_key')\n" \
- "dns_he_user = $(bashio::config 'dns.he_user')\n" \
- "dns_he_pass = $(bashio::config 'dns.he_pass')\n" \
- "dns_easydns_endpoint = $(bashio::config 'dns.easydns_endpoint')\n" \
- "dns_easydns_usertoken = $(bashio::config 'dns.easydns_token')\n" \
- "dns_easydns_userkey = $(bashio::config 'dns.easydns_key')\n" > /data/dnsapikey
+DNS_API_KEY=/data/dnsapikey
+DNS_MULTI_CREDS=/data/dns-multi.ini
-if bashio::config.exists 'dns.google_domains_zone'; then
- echo -e "dns_google_domains_zone = $(bashio::config 'dns.google_domains_zone')\n" >> /data/dnsapikey
+touch "${DNS_API_KEY}"
+chmod 0600 "${DNS_API_KEY}"
+touch "${DNS_MULTI_CREDS}"
+chmod 0600 "${DNS_MULTI_CREDS}"
+
+if bashio::config.exists 'dns.google_creds'; then
+ GOOGLE_CREDS="$(bashio::config 'dns.google_creds')"
+ if [ -f "/share/${GOOGLE_CREDS}" ]; then
+ cp -f "/share/${GOOGLE_CREDS}" "/data/google.json"
+ chmod 0600 "/data/google.json"
+ else
+ bashio::log.error "Google credentials file '${GOOGLE_CREDS}' not found in /share directory"
+ exit 1
+ fi
+fi
+
+if bashio::config.exists 'dns.azure_config'; then
+ bashio::log.warning "Using legacy certbot-dns-azure plugin (DEPRECATED)"
+ bashio::log.warning "The 'azure_config' option will be removed in a future version."
+ AZURE_CREDS="$(bashio::config 'dns.azure_config')"
+ if [ -f "/share/${AZURE_CREDS}" ]; then
+ cp -f "/share/${AZURE_CREDS}" "/data/azure_creds"
+ chmod 0600 "/data/azure_creds"
+ else
+ bashio::log.error "Azure credentials file '${AZURE_CREDS}' not found in /share directory"
+ exit 1
+ fi
fi
-# ClouDNS
-# Only a single non-empty auth option must be in /data/dnsapikey when using ClouDNS to avoid a certbot error
-if bashio::config.exists 'dns.cloudns_auth_id'; then
- echo -e "dns_cloudns_auth_id = $(bashio::config 'dns.cloudns_auth_id')\n" >> /data/dnsapikey
+# Warn/fail on deprecated options
+if bashio::config.has_value 'dns.cloudns_sub_auth_user'; then
+ bashio::log.error "cloudns_sub_auth_user is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
fi
-if bashio::config.exists 'dns.cloudns_sub_auth_id'; then
- echo -e "dns_cloudns_sub_auth_id = $(bashio::config 'dns.cloudns_sub_auth_id')\n" >> /data/dnsapikey
+
+if bashio::config.has_value 'dns.dreamhost_baseurl'; then
+ if [ "$(bashio::config 'dns.dreamhost_baseurl')" != "https://api.dreamhost.com/" ]; then
+ bashio::log.error "dreamhost_baseurl is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
+ else
+ bashio::log.warning "dreamhost_baseurl is not required since Letsencrypt Home Assistant App v6.0.0, please remove it from your configuration."
+ fi
+fi
+
+if bashio::config.has_value 'dns.gandi_sharing_id'; then
+ bashio::log.error "gandi_sharing_id is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
fi
-if bashio::config.exists 'dns.cloudns_sub_auth_user'; then
- echo -e "dns_cloudns_sub_auth_user = $(bashio::config 'dns.cloudns_sub_auth_user')\n" >> /data/dnsapikey
+if bashio::config.has_value 'dns.ionos_endpoint'; then
+ if [ "$(bashio::config 'dns.ionos_endpoint')" != "https://api.hosting.ionos.com" ]; then
+ bashio::log.error "ionos_endpoint is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
+ else
+ bashio::log.warning "ionos_endpoint is not required since Letsencrypt Home Assistant App v6.0.0, please remove it from your configuration."
+ fi
fi
-chmod 600 /data/dnsapikey
+if bashio::config.has_value 'dns.joker_domain'; then
+ bashio::log.error "joker_domain is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
+fi
-## Prepare TransIP RSA key
-if bashio::config.exists 'dns.transip_api_key'; then
- TRANSIP_API_KEY=$(bashio::config 'dns.transip_api_key')
- echo "${TRANSIP_API_KEY}" | openssl rsa -out /data/transip-rsa.key
- chmod 600 /data/transip-rsa.key
+if bashio::config.has_value 'dns.linode_version'; then
+ if [ "$(bashio::config 'dns.linode_version')" != "4" ]; then
+ bashio::log.error "Only Linode API v4 is supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
+ else
+ bashio::log.warning "linode_version is not required since Letsencrypt Home Assistant App v6.0.0, please remove it from your configuration."
+ fi
+fi
+
+if bashio::config.has_value 'dns.rfc2136_sign_query'; then
+ bashio::log.error "rfc2136_sign_query is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
+fi
+
+if bashio::config.has_value 'dns.transip_global_key'; then
+ bashio::log.error "transip_global_key is not supported since Letsencrypt Home Assistant App v6.0.0."
+ exit 1
fi
# Cleanup removed add-on options
if bashio::config.exists 'dns.cloudxns_api_key'; then
- bashio::addon.option 'dns.cloudxns_api_key'
+ bashio::addon.option 'dns.cloudxns_api_key'
fi
if bashio::config.exists 'dns.cloudxns_secret_key'; then
- bashio::addon.option 'dns.cloudxns_secret_key'
+ bashio::addon.option 'dns.cloudxns_secret_key'
fi
if bashio::config.exists 'keytype'; then
bashio::addon.option 'keytype'
fi
+if bashio::config.exists 'dns.google_domains_access_token'; then
+ bashio::addon.option 'dns.google_domains_access_token'
+fi
+if bashio::config.exists 'dns.google_domains_zone'; then
+ bashio::addon.option 'dns.google_domains_zone'
+fi
diff --git a/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish b/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish
index ee6e08eee22..21f86c75bc2 100755
--- a/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish
+++ b/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish
@@ -1,6 +1,7 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
-# Take down the S6 supervision tree when service is done
+# Take down the S6 supervision tree when service is done
# ==============================================================================
/run/s6/basedir/bin/halt
diff --git a/letsencrypt/rootfs/etc/services.d/lets-encrypt/run b/letsencrypt/rootfs/etc/services.d/lets-encrypt/run
index 48e03e4ac0f..995ae26353c 100755
--- a/letsencrypt/rootfs/etc/services.d/lets-encrypt/run
+++ b/letsencrypt/rootfs/etc/services.d/lets-encrypt/run
@@ -1,12 +1,17 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start sshd service if enabled
# ==============================================================================
CERT_DIR=/data/letsencrypt
WORK_DIR=/data/workdir
-PROVIDER_ARGUMENTS=()
-ACME_CUSTOM_SERVER_ARGUMENTS=()
+DNS_API_KEY=/data/dnsapikey
+DNS_MULTI_CREDS=/data/dns-multi.ini
+ACME_ARGUMENTS=()
KEY_ARGUMENTS=()
+EAB_ARGUMENTS=()
+ADDITIONAL_ARGS=()
EMAIL=$(bashio::config 'email')
DOMAINS=$(bashio::config 'domains')
@@ -15,9 +20,21 @@ CERTFILE=$(bashio::config 'certfile')
CHALLENGE=$(bashio::config 'challenge')
DNS_PROVIDER=$(bashio::config 'dns.provider')
ACME_SERVER=$(bashio::config 'acme_server')
-ACME_ROOT_CA=$(bashio::config 'acme_root_ca_cert')
+ACME_ROOT_CA_CERT=$(bashio::config 'acme_root_ca_cert')
+EAB_KID=$(bashio::config 'eab_kid')
+EAB_HMAC_KEY=$(bashio::config 'eab_hmac_key')
+DRY_RUN=$(bashio::config 'dry_run')
+TEST_CERT=$(bashio::config 'test_cert')
+VERBOSE=$(bashio::config 'verbose')
+
+# Legacy providers not supported by lego/certbot-dns-multi
+LEGACY_PROVIDERS="dns-eurodns dns-gehirn dns-noris"
+
+# Deprecated providers not having feature parity in lego/certbot-dns-multi
+DEPRECATED_PROVIDERS="dns-azure dns-he"
if [ "${CHALLENGE}" == "dns" ]; then
+ bashio::config.require 'dns.provider'
bashio::log.info "Selected DNS Provider: ${DNS_PROVIDER}"
PROPAGATION_SECONDS=60
@@ -25,180 +42,534 @@ if [ "${CHALLENGE}" == "dns" ]; then
PROPAGATION_SECONDS="$(bashio::config 'dns.propagation_seconds')"
fi
bashio::log.info "Use propagation seconds: ${PROPAGATION_SECONDS}"
-else
- bashio::log.info "Selected http verification"
-fi
-# AWS
-if [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-route53" ]; then
- bashio::config.require 'dns.aws_access_key_id'
- bashio::config.require 'dns.aws_secret_access_key'
-
- AWS_ACCESS_KEY_ID="$(bashio::config 'dns.aws_access_key_id')"
- AWS_SECRET_ACCESS_KEY="$(bashio::config 'dns.aws_secret_access_key')"
-
- export AWS_ACCESS_KEY_ID
- export AWS_SECRET_ACCESS_KEY
- PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}")
-#Google
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-google" ]; then
- bashio::config.require 'dns.google_creds'
- GOOGLE_CREDS="$(bashio::config 'dns.google_creds')"
-
- export GOOGLE_CREDS
- if [ -f "/share/${GOOGLE_CREDS}" ]; then
- cp -f "/share/${GOOGLE_CREDS}" "/data/${GOOGLE_CREDS}"
- chmod 600 "/data/${GOOGLE_CREDS}"
- else
- bashio::log.info "Google Credentials File doesnt exists in folder share."
- fi
- PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/${GOOGLE_CREDS}")
-#Google Domains
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-google-domains" ]; then
- bashio::config.require 'dns.google_domains_access_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-#Namecheap
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-namecheap" ]; then
- bashio::config.require 'dns.namecheap_username'
- bashio::config.require 'dns.namecheap_api_key'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-#Netcup
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-netcup" ]; then
- bashio::config.require 'dns.netcup_customer_id'
- bashio::config.require 'dns.netcup_api_key'
- bashio::config.require 'dns.netcup_api_password'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-#TransIP
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-transip" ]; then
- bashio::config.require.username 'dns.transip_username'
- bashio::config.require 'dns.transip_api_key'
- if (( PROPAGATION_SECONDS < 240 )); then
- bashio::log.info "Increasing DNS propagation limit for TransIP to at least 240 seconds."
- PROPAGATION_SECONDS=240
- fi
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
+ # Check if this is a legacy provider (not supported by dns-multi)
+ # shellcheck disable=SC2076
+ if [[ " ${LEGACY_PROVIDERS} " =~ " ${DNS_PROVIDER} " ]]; then
+ bashio::log.info "Using dedicated certbot plugin for ${DNS_PROVIDER}"
-# CloudFlare
-elif [ "${DNS_PROVIDER}" == "dns-cloudflare" ]; then
- if bashio::config.exists 'dns.cloudflare_api_token'; then
- bashio::log.info "Use CloudFlare token"
- echo "dns_cloudflare_api_token = $(bashio::config 'dns.cloudflare_api_token')" >> "/data/dnsapikey"
- else
- bashio::log.warning "Use CloudFlare global key (not recommended!)"
- echo -e "dns_cloudflare_email = $(bashio::config 'dns.cloudflare_email')\n" \
- "dns_cloudflare_api_key = $(bashio::config 'dns.cloudflare_api_key')\n" >> "/data/dnsapikey"
- fi
+ case "${DNS_PROVIDER}" in
+ # Eurodns
+ 'dns-eurodns')
+ bashio::config.require 'dns.eurodns_applicationId'
+ bashio::config.require 'dns.eurodns_apiKey'
- PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--dns-cloudflare-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# DirectAdmin
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-directadmin" ]; then
- bashio::config.require 'dns.directadmin_url'
- bashio::config.require 'dns.directadmin_username'
- bashio::config.require 'dns.directadmin_password'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-#DuckDNS
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-duckdns" ]; then
- bashio::config.require 'dns.duckdns_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# Gandi
-elif [ "${DNS_PROVIDER}" == "dns-gandi" ]; then
- if bashio::config.exists 'dns.gandi_sharing_id'; then
- bashio::log.info "Use Gandi sharing ID"
- echo "dns_gandi_sharing_id = $(bashio::config 'dns.gandi_sharing_id')" >> "/data/dnsapikey"
- fi
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}" )
-
-# Hetzner
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-hetzner" ]; then
- bashio::config.require 'dns.hetzner_api_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "dns-hetzner" "--dns-hetzner-credentials" "/data/dnsapikey" "--dns-hetzner-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# Infomaniak
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-infomaniak" ]; then
- bashio::config.require 'dns.infomaniak_api_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# Njalla
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-njalla" ]; then
- bashio::config.require 'dns.njalla_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# rfc2136
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-rfc2136" ]; then
- PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--dns-rfc2136-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# Azure
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-azure" ]; then
- bashio::config.require 'dns.azure_config'
- AZURE_CREDS="$(bashio::config 'dns.azure_config')"
-
- export AZURE_CREDS
- if [ -f "/share/${AZURE_CREDS}" ]; then
- cp -f "/share/${AZURE_CREDS}" "/data/azure_creds"
- chmod 600 "/data/azure_creds"
+ echo "dns_eurodns_apiKey = $(bashio::config 'dns.eurodns_apiKey')" > "${DNS_API_KEY}"
+ echo "dns_eurodns_applicationId = $(bashio::config 'dns.eurodns_applicationId')" >> "${DNS_API_KEY}"
+
+ ACME_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "${DNS_API_KEY}" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
+ ;;
+
+ # Gehirn
+ 'dns-gehirn')
+ bashio::config.require 'dns.gehirn_api_token'
+ bashio::config.require 'dns.gehirn_api_secret'
+
+ echo "dns_gehirn_api_secret = $(bashio::config 'dns.gehirn_api_secret')" > "${DNS_API_KEY}"
+ echo "dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')" >> "${DNS_API_KEY}"
+
+ ACME_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "${DNS_API_KEY}")
+ ;;
+
+ # noris network
+ 'dns-noris')
+ bashio::config.require 'dns.noris_token'
+
+ echo "dns_noris_token = $(bashio::config 'dns.noris_token')" > "${DNS_API_KEY}"
+
+ ACME_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "${DNS_API_KEY}" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
+ ;;
+ esac
+ elif [[ " ${DEPRECATED_PROVIDERS} " =~ " ${DNS_PROVIDER} " ]]; then
+ bashio::log.warning "Using deprecated certbot plugin for ${DNS_PROVIDER}"
+
+ case "${DNS_PROVIDER}" in
+ # Azure
+ 'dns-azure')
+ bashio::log.warning "The dns-azure provider is deprecated, please migrate to generic lego configuration using dns-lego provider"
+
+ # File is copied during container init by file-structure.sh
+ ACME_ARGUMENTS+=("--authenticator" "dns-azure" "--dns-azure-config" "/data/azure_creds" "--dns-azure-propagation-seconds" "${PROPAGATION_SECONDS}")
+ ;;
+ # Hurricane Electric DNS
+ 'dns-he')
+ bashio::log.warning "The dns-he provider is deprecated, please migrate to generic lego configuration using dns-lego provider"
+
+ bashio::config.require 'dns.he_user'
+ bashio::config.require 'dns.he_pass'
+
+ echo -e "dns_hurricane_electric_pass = $(bashio::config 'dns.he_pass')\n" \
+ "dns_hurricane_electric_user = $(bashio::config 'dns.he_user')" > "${DNS_API_KEY}"
+
+ ACME_ARGUMENTS+=("--authenticator" "dns-hurricane_electric" "--dns-hurricane_electric-credentials" "/data/dnsapikey" "--dns-hurricane_electric-propagation-seconds" "${PROPAGATION_SECONDS}")
+ ;;
+ esac
else
- bashio::log.info "Azure credentials file doesn't exist in folder share."
+ # Use certbot-dns-multi for all other providers
+ bashio::log.info "Using certbot-dns-multi for ${DNS_PROVIDER}"
+
+ # Some providers use a different env var prefix than the uppercased provider name
+ PROVIDER_ENV_PREFIX=""
+
+ # Map config provider names to lego provider names
+ declare -A LEGO_PROVIDERS=(
+ ["dns-cloudflare"]="cloudflare"
+ ["dns-cloudns"]="cloudns"
+ ["dns-desec"]="desec"
+ ["dns-digitalocean"]="digitalocean"
+ ["dns-directadmin"]="directadmin"
+ ["dns-dnsimple"]="dnsimple"
+ ["dns-dnsmadeeasy"]="dnsmadeeasy"
+ ["dns-domainoffensive"]="dode"
+ ["dns-dreamhost"]="dreamhost"
+ ["dns-duckdns"]="duckdns"
+ ["dns-dynu"]="dynu"
+ ["dns-easydns"]="easydns"
+ ["dns-gandi"]="gandiv5"
+ ["dns-godaddy"]="godaddy"
+ ["dns-google"]="gcloud"
+ ["dns-hetzner"]="hetzner"
+ ["dns-infomaniak"]="infomaniak"
+ ["dns-inwx"]="inwx"
+ ["dns-ionos"]="ionos"
+ ["dns-joker"]="joker"
+ ["dns-linode"]="linode"
+ ["dns-loopia"]="loopia"
+ ["dns-luadns"]="luadns"
+ ["dns-mijn-host"]="mijnhost"
+ ["dns-namecheap"]="namecheap"
+ ["dns-netcup"]="netcup"
+ ["dns-njalla"]="njalla"
+ ["dns-nsone"]="ns1"
+ ["dns-ovh"]="ovh"
+ ["dns-plesk"]="plesk"
+ ["dns-porkbun"]="porkbun"
+ ["dns-rfc2136"]="rfc2136"
+ ["dns-route53"]="route53"
+ ["dns-sakuracloud"]="sakuracloud"
+ ["dns-simply"]="simply"
+ ["dns-transip"]="transip"
+ ["dns-websupport"]="websupport"
+ )
+
+ # All other providers use dns-multi
+ LEGO_PROVIDER="${LEGO_PROVIDERS[$DNS_PROVIDER]-}"
+ if [ -z "${LEGO_PROVIDER}" ]; then
+ LEGO_PROVIDER="$(bashio::config 'dns.lego_provider')"
+ if [ -n "${LEGO_PROVIDER}" ]; then
+ bashio::log.info "Using custom lego provider from config: ${LEGO_PROVIDER}"
+ else
+ bashio::log.error "Unknown DNS provider: ${DNS_PROVIDER}"
+ exit 1
+ fi
+ fi
+
+ # Start building the dns-multi credentials file
+ echo "# generated by letsencrypt app startup script" > "${DNS_MULTI_CREDS}"
+ echo "dns_multi_provider = ${LEGO_PROVIDER}" >> "${DNS_MULTI_CREDS}"
+
+ # Provider-specific credential mapping to lego environment variables
+ case "${DNS_PROVIDER}" in
+ 'dns-lego')
+ bashio::config.require 'dns.lego_provider'
+
+ # Add custom environment variables for lego provider
+ if bashio::config.has_value 'dns.lego_env'; then
+ LEGO_ENV_COUNT=$(bashio::config 'dns.lego_env | length')
+ for (( i=0; i < LEGO_ENV_COUNT; i++ )); do
+ env_entry="$(bashio::config "dns.lego_env[${i}]")"
+ if [[ "${env_entry}" != *"="* ]]; then
+ bashio::log.error "Invalid lego_env entry (must be KEY=VALUE): ${env_entry}"
+ exit 1
+ fi
+ echo "${env_entry}" >> "${DNS_MULTI_CREDS}"
+ done
+ else
+ bashio::log.error "dns.lego_env must be configured for dns-lego provider"
+ exit 1
+ fi
+ ;;
+ # CloudFlare
+ 'dns-cloudflare')
+ if bashio::config.exists 'dns.cloudflare_api_token'; then
+ bashio::log.info "Using CloudFlare token"
+ echo "CLOUDFLARE_DNS_API_TOKEN=$(bashio::config 'dns.cloudflare_api_token')" >> "${DNS_MULTI_CREDS}"
+ else
+ bashio::log.warning "Using CloudFlare global key (not recommended!)"
+ echo "CF_API_EMAIL=$(bashio::config 'dns.cloudflare_email')" >> "${DNS_MULTI_CREDS}"
+ echo "CF_API_KEY=$(bashio::config 'dns.cloudflare_api_key')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # ClouDNS
+ 'dns-cloudns')
+ bashio::config.require 'dns.cloudns_auth_password'
+ echo "CLOUDNS_AUTH_PASSWORD=$(bashio::config 'dns.cloudns_auth_password')" >> "${DNS_MULTI_CREDS}"
+ if bashio::config.exists 'dns.cloudns_auth_id'; then
+ echo "CLOUDNS_AUTH_ID=$(bashio::config 'dns.cloudns_auth_id')" >> "${DNS_MULTI_CREDS}"
+ fi
+ if bashio::config.exists 'dns.cloudns_sub_auth_id'; then
+ echo "CLOUDNS_SUB_AUTH_ID=$(bashio::config 'dns.cloudns_sub_auth_id')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # deSEC.io
+ 'dns-desec')
+ bashio::config.require 'dns.desec_token'
+ echo "DESEC_TOKEN=$(bashio::config 'dns.desec_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Digital Ocean
+ 'dns-digitalocean')
+ bashio::config.require 'dns.digitalocean_token'
+ echo "DO_AUTH_TOKEN=$(bashio::config 'dns.digitalocean_token')" >> "${DNS_MULTI_CREDS}"
+ # Uppercased provider name differs from variable prefix
+ PROVIDER_ENV_PREFIX="DO"
+ ;;
+
+ # DirectAdmin
+ 'dns-directadmin')
+ bashio::config.require 'dns.directadmin_url'
+ bashio::config.require 'dns.directadmin_username'
+ bashio::config.require 'dns.directadmin_password'
+ echo "DIRECTADMIN_API_URL=$(bashio::config 'dns.directadmin_url')" >> "${DNS_MULTI_CREDS}"
+ echo "DIRECTADMIN_USERNAME=$(bashio::config 'dns.directadmin_username')" >> "${DNS_MULTI_CREDS}"
+ echo "DIRECTADMIN_PASSWORD=$(bashio::config 'dns.directadmin_password')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # DNSimple
+ 'dns-dnsimple')
+ bashio::config.require 'dns.dnsimple_token'
+ echo "DNSIMPLE_OAUTH_TOKEN=$(bashio::config 'dns.dnsimple_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # DNS Made Easy
+ 'dns-dnsmadeeasy')
+ bashio::config.require 'dns.dnsmadeeasy_api_key'
+ bashio::config.require 'dns.dnsmadeeasy_secret_key'
+ echo "DNSMADEEASY_API_KEY=$(bashio::config 'dns.dnsmadeeasy_api_key')" >> "${DNS_MULTI_CREDS}"
+ echo "DNSMADEEASY_API_SECRET=$(bashio::config 'dns.dnsmadeeasy_secret_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Domain Offensive (do.de)
+ 'dns-domainoffensive')
+ bashio::config.require 'dns.domainoffensive_token'
+ echo "DODE_TOKEN=$(bashio::config 'dns.domainoffensive_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # DreamHost
+ 'dns-dreamhost')
+ bashio::config.require 'dns.dreamhost_api_key'
+ echo "DREAMHOST_API_KEY=$(bashio::config 'dns.dreamhost_api_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Duck DNS
+ 'dns-duckdns')
+ bashio::config.require 'dns.duckdns_token'
+ echo "DUCKDNS_TOKEN=$(bashio::config 'dns.duckdns_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Dynu
+ 'dns-dynu')
+ bashio::config.require 'dns.dynu_auth_token'
+ echo "DYNU_API_KEY=$(bashio::config 'dns.dynu_auth_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # EasyDNS
+ 'dns-easydns')
+ bashio::config.require 'dns.easydns_key'
+ bashio::config.require 'dns.easydns_token'
+ echo "EASYDNS_KEY=$(bashio::config 'dns.easydns_key')" >> "${DNS_MULTI_CREDS}"
+ echo "EASYDNS_TOKEN=$(bashio::config 'dns.easydns_token')" >> "${DNS_MULTI_CREDS}"
+ if bashio::config.exists 'dns.easydns_endpoint'; then
+ echo "EASYDNS_ENDPOINT=$(bashio::config 'dns.easydns_endpoint')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # Gandi Live DNS (v5)
+ 'dns-gandi')
+ if bashio::config.exists 'dns.gandi_token'; then
+ bashio::log.info "Using Gandi personal access token"
+ echo "GANDIV5_PERSONAL_ACCESS_TOKEN=$(bashio::config 'dns.gandi_token')" >> "${DNS_MULTI_CREDS}"
+ elif bashio::config.exists 'dns.gandi_api_key'; then
+ bashio::log.warning "Using Gandi API key (deprecated)"
+ echo "GANDIV5_API_KEY=$(bashio::config 'dns.gandi_api_key')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # Go Daddy
+ 'dns-godaddy')
+ bashio::config.require 'dns.godaddy_key'
+ bashio::config.require 'dns.godaddy_secret'
+ echo "GODADDY_API_KEY=$(bashio::config 'dns.godaddy_key')" >> "${DNS_MULTI_CREDS}"
+ echo "GODADDY_API_SECRET=$(bashio::config 'dns.godaddy_secret')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Google Cloud
+ 'dns-google')
+ bashio::config.require 'dns.google_creds'
+ # File is copied during container init by file-structure.sh
+ echo "GCE_SERVICE_ACCOUNT_FILE=/data/google.json" >> "${DNS_MULTI_CREDS}"
+ # Uppercased provider name differs from variable prefix
+ PROVIDER_ENV_PREFIX="GCE"
+ ;;
+
+ # Hetzner
+ 'dns-hetzner')
+ bashio::config.require 'dns.hetzner_api_token'
+ echo "HETZNER_API_TOKEN=$(bashio::config 'dns.hetzner_api_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Infomaniak
+ 'dns-infomaniak')
+ bashio::config.require 'dns.infomaniak_api_token'
+ echo "INFOMANIAK_ACCESS_TOKEN=$(bashio::config 'dns.infomaniak_api_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # INWX
+ 'dns-inwx')
+ bashio::config.require 'dns.inwx_username'
+ bashio::config.require 'dns.inwx_password'
+ echo "INWX_USERNAME=$(bashio::config 'dns.inwx_username')" >> "${DNS_MULTI_CREDS}"
+ echo "INWX_PASSWORD=$(bashio::config 'dns.inwx_password')" >> "${DNS_MULTI_CREDS}"
+ if bashio::config.exists 'dns.inwx_shared_secret'; then
+ echo "INWX_SHARED_SECRET=$(bashio::config 'dns.inwx_shared_secret')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # IONOS
+ 'dns-ionos')
+ bashio::config.require 'dns.ionos_prefix'
+ bashio::config.require 'dns.ionos_secret'
+ # IONOS API key format is prefix.secret
+ echo "IONOS_API_KEY=$(bashio::config 'dns.ionos_prefix').$(bashio::config 'dns.ionos_secret')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Joker
+ 'dns-joker')
+ bashio::config.require 'dns.joker_username'
+ bashio::config.require 'dns.joker_password'
+ echo "JOKER_USERNAME=$(bashio::config 'dns.joker_username')" >> "${DNS_MULTI_CREDS}"
+ echo "JOKER_PASSWORD=$(bashio::config 'dns.joker_password')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Linode (v4)
+ 'dns-linode')
+ bashio::config.require 'dns.linode_key'
+ echo "LINODE_TOKEN=$(bashio::config 'dns.linode_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Loopia
+ 'dns-loopia')
+ bashio::config.require 'dns.loopia_user'
+ bashio::config.require 'dns.loopia_password'
+ if (( PROPAGATION_SECONDS < 900 )); then
+ bashio::log.info "Increasing DNS propagation limit for Loopia to at least 900 seconds due to caching issues."
+ PROPAGATION_SECONDS=900
+ fi
+ echo "LOOPIA_API_USER=$(bashio::config 'dns.loopia_user')" >> "${DNS_MULTI_CREDS}"
+ echo "LOOPIA_API_PASSWORD=$(bashio::config 'dns.loopia_password')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # LuaDNS
+ 'dns-luadns')
+ bashio::config.require 'dns.luadns_email'
+ bashio::config.require 'dns.luadns_token'
+ echo "LUADNS_API_USERNAME=$(bashio::config 'dns.luadns_email')" >> "${DNS_MULTI_CREDS}"
+ echo "LUADNS_API_TOKEN=$(bashio::config 'dns.luadns_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # mijn.host
+ 'dns-mijn-host')
+ bashio::config.require 'dns.mijn_host_api_key'
+ echo "MIJNHOST_API_KEY=$(bashio::config 'dns.mijn_host_api_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Namecheap
+ 'dns-namecheap')
+ bashio::config.require 'dns.namecheap_username'
+ bashio::config.require 'dns.namecheap_api_key'
+ echo "NAMECHEAP_API_USER=$(bashio::config 'dns.namecheap_username')" >> "${DNS_MULTI_CREDS}"
+ echo "NAMECHEAP_API_KEY=$(bashio::config 'dns.namecheap_api_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Netcup
+ 'dns-netcup')
+ bashio::config.require 'dns.netcup_customer_id'
+ bashio::config.require 'dns.netcup_api_key'
+ bashio::config.require 'dns.netcup_api_password'
+ echo "NETCUP_CUSTOMER_NUMBER=$(bashio::config 'dns.netcup_customer_id')" >> "${DNS_MULTI_CREDS}"
+ echo "NETCUP_API_KEY=$(bashio::config 'dns.netcup_api_key')" >> "${DNS_MULTI_CREDS}"
+ echo "NETCUP_API_PASSWORD=$(bashio::config 'dns.netcup_api_password')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Njalla
+ 'dns-njalla')
+ bashio::config.require 'dns.njalla_token'
+ echo "NJALLA_TOKEN=$(bashio::config 'dns.njalla_token')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # NS1
+ 'dns-nsone')
+ bashio::config.require 'dns.nsone_api_key'
+ echo "NS1_API_KEY=$(bashio::config 'dns.nsone_api_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # OVH
+ 'dns-ovh')
+ bashio::config.require 'dns.ovh_application_key'
+ bashio::config.require 'dns.ovh_application_secret'
+ bashio::config.require 'dns.ovh_consumer_key'
+ bashio::config.require 'dns.ovh_endpoint'
+ echo "OVH_APPLICATION_KEY=$(bashio::config 'dns.ovh_application_key')" >> "${DNS_MULTI_CREDS}"
+ echo "OVH_APPLICATION_SECRET=$(bashio::config 'dns.ovh_application_secret')" >> "${DNS_MULTI_CREDS}"
+ echo "OVH_CONSUMER_KEY=$(bashio::config 'dns.ovh_consumer_key')" >> "${DNS_MULTI_CREDS}"
+ echo "OVH_ENDPOINT=$(bashio::config 'dns.ovh_endpoint')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # plesk.com
+ 'dns-plesk')
+ bashio::config.require 'dns.plesk_username'
+ bashio::config.require 'dns.plesk_password'
+ bashio::config.require 'dns.plesk_api_url'
+ if (( PROPAGATION_SECONDS < 120 )); then
+ bashio::log.info "Increasing DNS propagation limit for Plesk to at least 120 seconds."
+ PROPAGATION_SECONDS=120
+ fi
+ echo "PLESK_SERVER_BASE_URL=$(bashio::config 'dns.plesk_api_url')" >> "${DNS_MULTI_CREDS}"
+ echo "PLESK_USERNAME=$(bashio::config 'dns.plesk_username')" >> "${DNS_MULTI_CREDS}"
+ echo "PLESK_PASSWORD=$(bashio::config 'dns.plesk_password')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Porkbun
+ 'dns-porkbun')
+ bashio::config.require 'dns.porkbun_key'
+ bashio::config.require 'dns.porkbun_secret'
+ echo "PORKBUN_API_KEY=$(bashio::config 'dns.porkbun_key')" >> "${DNS_MULTI_CREDS}"
+ echo "PORKBUN_SECRET_API_KEY=$(bashio::config 'dns.porkbun_secret')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # RFC2136
+ 'dns-rfc2136')
+ bashio::config.require 'dns.rfc2136_server'
+ bashio::config.require 'dns.rfc2136_name'
+ bashio::config.require 'dns.rfc2136_secret'
+ RFC2136_PORT=$(bashio::config 'dns.rfc2136_port')
+ if [ -n "${RFC2136_PORT}" ]; then
+ echo "RFC2136_NAMESERVER=$(bashio::config 'dns.rfc2136_server'):${RFC2136_PORT}" >> "${DNS_MULTI_CREDS}"
+ else
+ echo "RFC2136_NAMESERVER=$(bashio::config 'dns.rfc2136_server')" >> "${DNS_MULTI_CREDS}"
+ fi
+ echo "RFC2136_TSIG_KEY=$(bashio::config 'dns.rfc2136_name')" >> "${DNS_MULTI_CREDS}"
+ echo "RFC2136_TSIG_SECRET=$(bashio::config 'dns.rfc2136_secret')" >> "${DNS_MULTI_CREDS}"
+ if bashio::config.exists 'dns.rfc2136_algorithm'; then
+ echo "RFC2136_TSIG_ALGORITHM=$(bashio::config 'dns.rfc2136_algorithm')" >> "${DNS_MULTI_CREDS}"
+ fi
+ ;;
+
+ # Amazon Route 53
+ 'dns-route53')
+ bashio::config.require 'dns.aws_access_key_id'
+ bashio::config.require 'dns.aws_secret_access_key'
+ echo "AWS_ACCESS_KEY_ID=$(bashio::config 'dns.aws_access_key_id')" >> "${DNS_MULTI_CREDS}"
+ echo "AWS_SECRET_ACCESS_KEY=$(bashio::config 'dns.aws_secret_access_key')" >> "${DNS_MULTI_CREDS}"
+ # Lego's AWS SDK requires a region to resolve the Route53 service endpoint.
+ # Route53 is a global service, so us-east-1 is the standard default.
+ AWS_REGION="us-east-1"
+ if bashio::config.has_value 'dns.aws_region'; then
+ AWS_REGION="$(bashio::config 'dns.aws_region')"
+ fi
+ echo "AWS_REGION=${AWS_REGION}" >> "${DNS_MULTI_CREDS}"
+ # Uppercased provider name differs from variable prefix
+ PROVIDER_ENV_PREFIX="AWS"
+ ;;
+
+ # SakuraCloud
+ 'dns-sakuracloud')
+ bashio::config.require 'dns.sakuracloud_api_token'
+ bashio::config.require 'dns.sakuracloud_api_secret'
+ echo "SAKURACLOUD_ACCESS_TOKEN=$(bashio::config 'dns.sakuracloud_api_token')" >> "${DNS_MULTI_CREDS}"
+ echo "SAKURACLOUD_ACCESS_TOKEN_SECRET=$(bashio::config 'dns.sakuracloud_api_secret')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # Simply.com
+ 'dns-simply')
+ bashio::config.require 'dns.simply_account_name'
+ bashio::config.require 'dns.simply_api_key'
+ echo "SIMPLY_ACCOUNT_NAME=$(bashio::config 'dns.simply_account_name')" >> "${DNS_MULTI_CREDS}"
+ echo "SIMPLY_API_KEY=$(bashio::config 'dns.simply_api_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+
+ # TransIP
+ 'dns-transip')
+ bashio::config.require 'dns.transip_username'
+ bashio::config.require 'dns.transip_api_key'
+
+ echo "TRANSIP_ACCOUNT_NAME=$(bashio::config 'dns.transip_username')" >> "${DNS_MULTI_CREDS}"
+ ## Prepare TransIP RSA key
+ TRANSIP_RSA_KEY=/data/transip-rsa.key
+ touch "${TRANSIP_RSA_KEY}"
+ chmod 0600 "${TRANSIP_RSA_KEY}"
+ if ! bashio::config 'dns.transip_api_key' | openssl rsa -out "${TRANSIP_RSA_KEY}" 2>/dev/null; then
+ bashio::log.error "Failed to process TransIP API RSA key. Ensure 'dns.transip_api_key' contains a valid RSA private key."
+ exit 1
+ fi
+ echo "TRANSIP_PRIVATE_KEY_PATH=${TRANSIP_RSA_KEY}" >> "${DNS_MULTI_CREDS}"
+
+ if (( PROPAGATION_SECONDS < 240 )); then
+ bashio::log.info "Increasing DNS propagation time for TransIP to at least 240 seconds."
+ PROPAGATION_SECONDS=240
+ fi
+ ;;
+
+ # WebSupport
+ 'dns-websupport')
+ bashio::config.require 'dns.websupport_identifier'
+ bashio::config.require 'dns.websupport_secret_key'
+ echo "WEBSUPPORT_API_KEY=$(bashio::config 'dns.websupport_identifier')" >> "${DNS_MULTI_CREDS}"
+ echo "WEBSUPPORT_SECRET=$(bashio::config 'dns.websupport_secret_key')" >> "${DNS_MULTI_CREDS}"
+ ;;
+ esac
+
+ # Set propagation timeout env var
+ if [ -z "${PROVIDER_ENV_PREFIX}" ]; then
+ PROVIDER_ENV_PREFIX=$(echo "${LEGO_PROVIDER}" | tr '[:lower:]-' '[:upper:]_')
+ fi
+ echo "${PROVIDER_ENV_PREFIX}_PROPAGATION_TIMEOUT=${PROPAGATION_SECONDS}" >> "${DNS_MULTI_CREDS}"
+
+ ACME_ARGUMENTS+=("--authenticator" "dns-multi" "--dns-multi-credentials" "${DNS_MULTI_CREDS}" "--dns-multi-propagation-seconds" "${PROPAGATION_SECONDS}")
fi
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-config" "/data/azure_creds")
-
-# INWX
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-inwx" ]; then
- bashio::config.require 'dns.inwx_username'
- bashio::config.require 'dns.inwx_password'
- bashio::config.require 'dns.inwx_shared_secret'
- PROVIDER_ARGUMENTS+=("-v" "--authenticator" "${DNS_PROVIDER}" "--dns-inwx-credentials" "/data/dnsapikey" "--dns-inwx-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-desec" ]; then
- bashio::config.require 'dns.desec_token'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-#Porkbun
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-porkbun" ]; then
- bashio::config.require 'dns.porkbun_key'
- bashio::config.require 'dns.porkbun_secret'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# ClouDNS
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-cloudns" ]; then
- bashio::config.require 'dns.cloudns_auth_password'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# Dreamhost
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-dreamhost" ]; then
- bashio::config.require 'dns.dreamhost_baseurl'
- bashio::config.require 'dns.dreamhost_api_key'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--dns-dreamhost-credentials" "/data/dnsapikey")
-
-# Hurricane Electric
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-he" ]; then
- bashio::config.require 'dns.he_user'
- bashio::config.require 'dns.he_pass'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-# easyDNS
-elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-easydns" ]; then
- bashio::config.require 'dns.easydns_key'
- bashio::config.require 'dns.easydns_token'
- bashio::config.require 'dns.easydns_endpoint'
- PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}")
-
-#All others
else
- PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey")
+ bashio::log.info "Selected HTTP verification"
+ ACME_ARGUMENTS+=("--standalone")
fi
-if bashio::config.has_value 'acme_server' ; then
- ACME_CUSTOM_SERVER_ARGUMENTS+=("--server" "${ACME_SERVER}")
-
+if bashio::config.has_value 'acme_server'; then
+ ACME_ARGUMENTS+=("--server" "${ACME_SERVER}")
if bashio::config.has_value 'acme_root_ca_cert'; then
- echo "${ACME_ROOT_CA}" > /tmp/root-ca-cert.crt
- # Certbot will automatically open the filepath contained in REQUESTS_CA_BUNDLE for extra CA cert
- export REQUESTS_CA_BUNDLE=/tmp/root-ca-cert.crt
+ bashio::log.info "Updating the trust store by adding the provided custom root certificate"
+ # Address potential header and footer errors from YAML mutiline configuration.
+ # Check the certificate and import it in the local trust store.
+ # Certbot relies on the Requests Python library, which uses a built-in
+ # trust store. This is replaced by the updated local trust store.
+ echo "${ACME_ROOT_CA_CERT}" \
+ | sed 's/----- /-----\n/g' | sed 's/ -----/\n-----/g' \
+ | openssl x509 > /usr/local/share/ca-certificates/acme_root_ca.crt \
+ && update-ca-certificates --fresh
fi
+else
+ # Relevant only for default Let's Encrypt servers.
+ ACME_ARGUMENTS+=(--preferred-chain 'ISRG Root X1')
+ if [ "${DRY_RUN}" = "true" ]; then
+ ADDITIONAL_ARGS+=("--dry-run")
+ fi
+ if [ "${TEST_CERT}" = "true" ]; then
+ ADDITIONAL_ARGS+=("--test-cert")
+ fi
+fi
+
+if [ "${VERBOSE}" = "true" ]; then
+ ADDITIONAL_ARGS+=("-vvv")
fi
# Gather all domains into a plaintext file
@@ -223,8 +594,9 @@ if bashio::config.exists 'key_type'; then
fi
else
bashio::log.info "Detecting existing certificate type for ${DOMAIN_ARR[1]}"
- readarray -t CBCERTS < <(certbot certificates --non-interactive --cert-name "${DOMAIN_ARR[1]}" --config-dir "$CERT_DIR" --work-dir "$WORK_DIR")
+ readarray -t CBCERTS < <(certbot certificates --non-interactive --cert-name "${DOMAIN_ARR[1]}" --config-dir "$CERT_DIR" --work-dir "$WORK_DIR")
for output in "${CBCERTS[@]}"; do
+ # shellcheck disable=SC2076
if [[ $output =~ "No certificates found." ]]; then
bashio::log.info "No certificate found - using 'ecdsa' key type."
KEY_ARGUMENTS+=("--key-type" "ecdsa")
@@ -243,25 +615,23 @@ else
done
fi
-# Generate a new certificate if necessary or expand a previous certificate if domains has changed
-if [ "$CHALLENGE" == "dns" ]; then
- certbot certonly --non-interactive --keep-until-expiring --expand \
- --email "$EMAIL" --agree-tos \
- "${KEY_ARGUMENTS[@]}" \
- --cert-name "${DOMAIN_ARR[1]}" "${DOMAIN_ARR[@]}" \
- --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \
- --preferred-challenges "$CHALLENGE" "${PROVIDER_ARGUMENTS[@]}" \
- --preferred-chain "ISRG Root X1"
-else
- certbot certonly --non-interactive --keep-until-expiring --expand \
- --email "$EMAIL" --agree-tos \
- "${KEY_ARGUMENTS[@]}" \
- --cert-name "${DOMAIN_ARR[1]}" "${DOMAIN_ARR[@]}" \
- --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \
- --preferred-challenges "$CHALLENGE" "${ACME_CUSTOM_SERVER_ARGUMENTS[@]}" --standalone \
- --preferred-chain "ISRG Root X1"
+# Set External Account Binding
+if bashio::config.has_value 'eab_kid' ; then
+ bashio::config.require 'eab_hmac_key'
+ EAB_ARGUMENTS+=("--eab-kid" "${EAB_KID}" "--eab-hmac-key" "${EAB_HMAC_KEY}")
fi
+# Generate a new certificate if necessary or expand a previous certificate if domains has changed
+certbot certonly --non-interactive --keep-until-expiring --expand \
+ --email "$EMAIL" --agree-tos \
+ "${KEY_ARGUMENTS[@]}" \
+ "${ADDITIONAL_ARGS[@]}" \
+ --cert-name "${DOMAIN_ARR[1]}" "${DOMAIN_ARR[@]}" \
+ --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \
+ --preferred-challenges "$CHALLENGE" \
+ "${ACME_ARGUMENTS[@]}" \
+ "${EAB_ARGUMENTS[@]}"
+
# Get the last modified cert directory and copy the cert and private key to store
# shellcheck disable=SC2012
CERT_DIR_LATEST="$(ls -td $CERT_DIR/live/*/ | head -1)"
diff --git a/letsencrypt/translations/en.yaml b/letsencrypt/translations/en.yaml
index 7696d0b5f06..86ee7dcef9d 100644
--- a/letsencrypt/translations/en.yaml
+++ b/letsencrypt/translations/en.yaml
@@ -17,18 +17,17 @@ configuration:
challenge:
name: Challenge
description: The type of challenge used to validate the domain.
+ acme_server:
+ name: Custom ACME Server
+ description: >-
+ By default, this app uses Let's Encrypt's servers. However, you can
+ specify a different ACME server.
acme_root_ca_cert:
name: ACME Root CA Certificate
description: >-
- If your custom ACME server uses a certificate signed by an untrusted
- certificate authority (CA), you can add the root certificate to the trust
- store by setting its content.
- acme_server:
- name: ACME Server
- description: >-
- By default, The addon uses Let's Encrypt's default server at
- https://acme-v02.api.letsencrypt.org/. You can instruct the addon to use a
- different ACME server.
+ Only relevant with a custom ACME server using a certificate signed by an
+ untrusted certificate authority (CA) that requires addition to the trust
+ store.
dns:
name: DNS
description: DNS Provider configuration
@@ -42,5 +41,19 @@ configuration:
description: >-
Elliptic curve for ECDSA keys. This option must be used with Key Type
set to ECDSA. If unset the Certbot default will be used.
+ dry_run:
+ name: Dry Run
+ description: >-
+ Do a certbot dry-run for requesting the certificates from Let's Encrypt.
+ This is ignored if a custom server is used.
+ test_cert:
+ name: Issue test certificates
+ description: >-
+ Obtain a test certificate from Let's Encrypt staging server.
+ This is ignored if a custom server is used.
+ verbose:
+ name: Verbose Mode
+ description: >-
+ Run certbot in verbose mode.
network:
80/tcp: Only needed for http challenge
diff --git a/mariadb/CHANGELOG.md b/mariadb/CHANGELOG.md
index 0424d40993a..803fa242323 100644
--- a/mariadb/CHANGELOG.md
+++ b/mariadb/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## 2.7.2
+
+- Add option to configure MariaDB server parameters (see also [home-assistant/addons#3754](https://github.com/home-assistant/addons/issues/3754))
+
+## 2.7.1
+
+**Note:** Restart the add-on before upgrade if the current version is lower
+than 2.7.0! This is to ensure a clean stop right before the update (see also
+https://github.com/home-assistant/addons/issues/3566).
+
+- Increase MariaDB add-on shutdown timeout to 300s
+
+## 2.7.0
+
+- Update to Alpine 3.19
+
## 2.6.1
- Use proper log redirection during backup
@@ -34,6 +50,7 @@
- Update options schema for passwords
## 2.2.1
+
- Don't delete the mariadb.sys user, it's needed in MariaDB >= 10.4.13
## 2.2.0
diff --git a/mariadb/DOCS.md b/mariadb/DOCS.md
index 39c9912700a..4c66272ed13 100644
--- a/mariadb/DOCS.md
+++ b/mariadb/DOCS.md
@@ -1,26 +1,26 @@
-# Home Assistant Add-on: MariaDB
+# Home Assistant App: MariaDB
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "MariaDB" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "MariaDB" app and click it.
3. Click on the "INSTALL" button.
## How to use
1. Set the `logins` -> `password` field to something strong and unique.
-2. Start the add-on.
-3. Check the add-on log output to see the result.
+2. Start the app.
+3. Check the app log output to see the result.
4. Add the `recorder` integration to your Home Assistant configuration.
-## Add-on Configuration
+## App configuration
-The MariaDB server add-on can be tweaked to your likings. This section
-describes each of the add-on configuration options.
+The MariaDB server app can be tweaked to your likings. This section
+describes each of the app configuration options.
-Example add-on configuration:
+Example app configuration:
```yaml
databases:
@@ -74,6 +74,13 @@ If omitted, grants `ALL PRIVILEGES` to the user. Restricting privileges of the u
that Home Assistant uses is not recommended but if you want to allow other applications
to view recorder data should create a user limited to read-only access on the database.
+### Option: `mariadb_server_args` (optional)
+
+Some users have experienced [errors][migration-issues] during Home Assistant schema updates on large databases.
+Defining the recommended parameters can help if there is RAM available.
+
+Example: `--innodb_buffer_pool_size=512M`
+
## Home Assistant Configuration
MariaDB will be used by the `recorder` and `history` components within Home Assistant. For more information about setting this up, see the [recorder integration][mariadb-ha-recorder] documentation for Home Assistant.
@@ -101,6 +108,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue].
[username]: https://mariadb.com/kb/en/create-user/#user-name-component
[hostname]: https://mariadb.com/kb/en/create-user/#host-name-component
[grant]: https://mariadb.com/kb/en/grant/
+[migration-issues]: https://github.com/home-assistant/core/issues/125339
[mariadb-ha-recorder]: https://www.home-assistant.io/integrations/recorder/
[discord]: https://discord.gg/c5DvZ4e
[forum]: https://community.home-assistant.io
diff --git a/mariadb/Dockerfile b/mariadb/Dockerfile
index ceb644ed459..bf255ff1778 100644
--- a/mariadb/Dockerfile
+++ b/mariadb/Dockerfile
@@ -9,8 +9,7 @@ RUN apk add --no-cache \
pwgen
ENV \
- LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \
- S6_SERVICES_GRACETIME=18000
+ LD_PRELOAD="/usr/local/lib/libjemalloc.so.2"
# Copy data
COPY rootfs /
diff --git a/mariadb/README.md b/mariadb/README.md
index 2f55db670d3..217af0ff360 100644
--- a/mariadb/README.md
+++ b/mariadb/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: MariaDB
+# Home Assistant App: MariaDB
MariaDB database for Home Assistant.
@@ -6,7 +6,7 @@ MariaDB database for Home Assistant.
## About
-You can use this add-on to install MariaDB, which is an open-source (GPLv2 licensed) database. MariaDB can be used as the database backend for Home Assistant. For more information, please see [MariaDB][mariadb]
+You can use this app (formerly known as add-on) to install MariaDB, which is an open-source (GPLv2 licensed) database. MariaDB can be used as the database backend for Home Assistant. For more information, please see [MariaDB][mariadb]
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
diff --git a/mariadb/build.yaml b/mariadb/build.yaml
index 33700d0a31b..19306375de0 100644
--- a/mariadb/build.yaml
+++ b/mariadb/build.yaml
@@ -1,10 +1,7 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.16
- amd64: ghcr.io/home-assistant/amd64-base:3.16
- armhf: ghcr.io/home-assistant/armhf-base:3.16
- armv7: ghcr.io/home-assistant/armv7-base:3.16
- i386: ghcr.io/home-assistant/i386-base:3.16
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.19
+ amd64: ghcr.io/home-assistant/amd64-base:3.19
+ armhf: ghcr.io/home-assistant/armhf-base:3.19
+ armv7: ghcr.io/home-assistant/armv7-base:3.19
+ i386: ghcr.io/home-assistant/i386-base:3.19
diff --git a/mariadb/config.yaml b/mariadb/config.yaml
index 7140c07533c..828018ecd71 100644
--- a/mariadb/config.yaml
+++ b/mariadb/config.yaml
@@ -1,5 +1,5 @@
---
-version: 2.6.1
+version: 2.7.2
slug: mariadb
name: MariaDB
description: A SQL database server
@@ -38,7 +38,9 @@ schema:
CREATE VIEW|DELETE|DELETE HISTORY|DROP|EVENT|GRANT OPTION|INDEX|\
INSERT|LOCK TABLES|SELECT|SHOW VIEW|TRIGGER|UPDATE)?"
username: str
+ mariadb_server_args:
+ - str?
services:
- mysql:provide
startup: system
-timeout: 20
+timeout: 300
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish
index 01d0808bb59..5b47ebd627e 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish
@@ -1,9 +1,10 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when daemon fails
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run
index e486c2bf296..be4a0d6c2ee 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run
@@ -1,10 +1,22 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start MariaDB service
# ==============================================================================
+if bashio::config.has_value "mariadb_server_args"; then
+ readarray -t extra_args <<< "$(bashio::config 'mariadb_server_args')"
+ bashio::log.info "Starting MariaDB with command line parameters: ${extra_args[*]}"
+else
+ bashio::log.info "Starting MariaDB"
+fi
+
# Start mariadb
-bashio::log.info "Starting MariaDB"
mkdir -p /run/mysqld
-exec mysqld --datadir="${MARIADB_DATA}" --user=root < /dev/null
+
+if [ -z "${extra_args+x}" ] || [ ${#extra_args[@]} -eq 0 ]; then
+ exec mysqld --datadir="${MARIADB_DATA}" --user=root < /dev/null
+else
+ exec mysqld --datadir="${MARIADB_DATA}" --user=root "${extra_args[@]}" < /dev/null
+fi
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill
new file mode 100644
index 00000000000..94ca7aa4c37
--- /dev/null
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill
@@ -0,0 +1 @@
+295000
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish
index 0362b4f8ff9..1bd7048c0a8 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# MariaDB client (to lock tables for backups) stopped
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run
index 64c61092756..29e8cc3ff62 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start MariaDB client (to lock tables for backups)
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish
index 10ed2404217..5761b87dbec 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Unlock tables locked for backups
@@ -6,12 +7,14 @@
declare MARIADB_LOCK_CORE_PID
MARIADB_LOCK_CORE_PID=$(s6-svstat -o pid "/run/service/mariadb-lock-core")
+# shellcheck disable=SC2086
if bashio::var.equals ${MARIADB_LOCK_CORE_PID} -1; then
bashio::log.error "Invalid mariadb-lock-core process id ${MARIADB_LOCK_CORE_PID}"
bashio::exit.nok
fi
# File descriptor &4 is used as stdin for mysql, because &0 is closed after the mariadb-lock-core service is started
+# shellcheck disable=SC2086
echo "UNLOCK TABLES;" > /proc/${MARIADB_LOCK_CORE_PID}/fd/4
bashio::log.info "MariaDB tables unlocked"
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run
index 38ba3a6485c..44ecf545321 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Lock tables for backups
@@ -6,12 +7,14 @@
declare MARIADB_LOCK_CORE_PID
MARIADB_LOCK_CORE_PID=$(s6-svstat -o pid "/run/service/mariadb-lock-core")
+# shellcheck disable=SC2086
if bashio::var.equals ${MARIADB_LOCK_CORE_PID} -1; then
bashio::log.error "Invalid mariadb-lock-core process id ${MARIADB_LOCK_CORE_PID}"
bashio::exit.nok
fi
# File descriptor &4 is used as stdin for mysql, because &0 is closed after the mariadb-lock-core service is started
+# shellcheck disable=SC2086
echo "FLUSH TABLES WITH READ LOCK;" > /proc/${MARIADB_LOCK_CORE_PID}/fd/4
bashio::log.info "MariaDB tables locked"
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish
index a0719a3b1c3..59c6b743f57 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Post-start finalization of MariaDB service
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run
index fe7d792eb87..231072576f4 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Post-start initialization of MariaDB service
@@ -8,7 +9,9 @@ function execute_without_error_messages() {
local current_log_level="${__BASHIO_LOG_LEVELS[${__BASHIO_LOG_LEVEL}]}"
bashio::log.level fatal
local exit_code=0
+ # shellcheck disable=SC2068
$@ || exit_code=$?
+ # shellcheck disable=SC2086
bashio::log.level ${current_log_level}
return ${exit_code}
}
diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run
index 25ac5927d9e..5024041a543 100755
--- a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run
+++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Pre-start initialization of MariaDB service
@@ -11,8 +12,8 @@ if ! bashio::fs.directory_exists "${MARIADB_DATA}"; then
fi
# Save variables
-printf "${MARIADB_DATA}" > /var/run/s6/container_environment/MARIADB_DATA
-printf "${NEW_INSTALL}" > /var/run/s6/container_environment/NEW_INSTALL
+echo -n "${MARIADB_DATA}" > /var/run/s6/container_environment/MARIADB_DATA
+echo -n "${NEW_INSTALL}" > /var/run/s6/container_environment/NEW_INSTALL
# Redirect log output
mkdir -p "${MARIADB_DATA}"
diff --git a/mariadb/rootfs/usr/bin/lock-tables-for-backup b/mariadb/rootfs/usr/bin/lock-tables-for-backup
index b2ade4adf86..b63418732fc 100755
--- a/mariadb/rootfs/usr/bin/lock-tables-for-backup
+++ b/mariadb/rootfs/usr/bin/lock-tables-for-backup
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Lock tables for backup
diff --git a/mariadb/rootfs/usr/bin/unlock-tables-for-backup b/mariadb/rootfs/usr/bin/unlock-tables-for-backup
index 650b1f083c3..2d09c79ce17 100755
--- a/mariadb/rootfs/usr/bin/unlock-tables-for-backup
+++ b/mariadb/rootfs/usr/bin/unlock-tables-for-backup
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Unlock tables for backup
diff --git a/matter_server/CHANGELOG.md b/matter_server/CHANGELOG.md
index 5191eac482a..bd78ffce3a0 100644
--- a/matter_server/CHANGELOG.md
+++ b/matter_server/CHANGELOG.md
@@ -1,5 +1,120 @@
# Changelog
+## 8.2.2
+
+- Install make and gcc as well
+
+## 8.2.1
+
+- Install the necessary packages to allow BLE to work
+
+## 8.2.0
+
+- Switch to the new [matter.js-based Matter Server](https://github.com/matter-js/matterjs-server) when enabling the **Beta** option
+ - Existing data is migrated automatically with no user action required
+ - Users can switch back to the Python-based Matter Server at any time
+- Add Node.js to the add-on container
+
+## 8.1.2
+
+- Bump Python Matter Server to [8.1.2](https://github.com/matter-js/python-matter-server/releases/tag/8.1.2)
+
+## 8.1.1
+
+- Bump Python Matter Server to [8.1.1](https://github.com/matter-js/python-matter-server/releases/tag/8.1.1)
+
+## 8.1.0
+
+- Bump Python Matter Server to [8.1.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/8.1.0)
+- Update bashio to 0.17.1
+
+## 8.0.0
+
+- Bump Python Matter Server to [8.0.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/8.0.0)
+
+## 7.0.0
+
+- Bump Python Matter Server to [7.0.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/7.0.1)
+ - This updates Matter to 1.4
+- Update base image components to what is being used in Home Assistant Debian
+ base images:
+ - Update tempio to 2024.11.2
+ - Update s6-overlay to 3.1.6.2
+ - Update bashio to 0.16.2
+
+## 6.6.1
+
+- Bump Python Matter Server to [6.6.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.6.1)
+
+## 6.6.0
+
+- Bump Python Matter Server to [6.6.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.6.0)
+
+## 6.5.1
+
+- Bump Python Matter Server to [6.5.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.5.1)
+
+## 6.5.0
+
+- Bump Python Matter Server to [6.5.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.5.0)
+
+## 6.4.2
+
+- Add support for custom Matter Server arguments
+- Add support to install custom Matter Server and Matter SDK (CHIP) versions
+
+## 6.4.1
+
+- Bump Python Matter Server to [6.4.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.4.0)
+
+## 6.4.0
+
+- Use add-on config directory as update directory
+
+## 6.3.1
+
+- Fix Matter SDK log level when using beta flag
+
+## 6.3.0
+
+- Bump Python Matter Server to [6.3.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.3.0)
+
+## 6.2.1
+
+- Bump Python Matter Server to [6.2.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.2.1)
+
+## 6.1.2
+
+- Bump Python Matter Server to [6.1.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.2)
+
+## 6.1.1
+
+- Bump Python Matter Server to [6.1.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.1)
+
+## 6.1.0
+
+- Bump Python Matter Server to [6.1.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.0)
+ - This update is required for Home Assistant Core 2024.6.0
+
+## 6.0.0
+
+- Bump Python Matter Server to [6.0.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.0.0)
+ - This updates Matter to 1.3
+
+## 5.6.0
+
+- Bump Python Matter Server to [5.10.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.10.0)
+
+## 5.5.1
+
+- Fix logging in case fallback method for determining the primary network interface is used
+
+## 5.5.0
+
+- Bump Python Matter Server to [5.9.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.9.0)
+- Enable Ingress for the Python Matter Server built-in web interface
+- Store PAA root certificates in /data to avoid download on every startup (downloads once a day)
+
## 5.4.1
- Bump Python Matter Server to [5.8.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.8.1)
diff --git a/matter_server/DOCS.md b/matter_server/DOCS.md
index cdf7adb7a37..e8c4ed95795 100644
--- a/matter_server/DOCS.md
+++ b/matter_server/DOCS.md
@@ -1,36 +1,48 @@
-# Home Assistant Add-on: Matter Server
+# Home Assistant App: Matter Server
## Installation
-Use the following steps to install this add-on.
+Use the following steps to install this app.
-1. Click the Home Assistant My button below to open the add-on page on your
+1. Click the Home Assistant My button below to open the app page on your
Home Assistant instance.
- [![Open this add-on in your Home Assistant instance.][addon-badge]][addon]
+ [![Open this app in your Home Assistant instance.][addon-badge]][addon]
-1. Click the "Install" button to install the add-on.
+1. Click the "Install" button to install the app.
## How to use
-Start the Matter Server add-on to make the WebSocket available to Home
+Start the Matter Server app to make the WebSocket available to Home
Assistant Core. Install the [Matter integration][matter_integration]
in Home Assistant Core.
### Access WebSocket interface externally (advanced)
-By default, the Python Matter Server's WebSocket interface is only exposed
-internally. It is still possible to enable access through the host interface
+By default, the OHF Matter Server's WebSocket interface is only exposed
+internally. It is still possible to enable access through the host interface.
To do so, click on "Show disabled ports" and enter a port (e.g. 5580) in the
Matter Server WebSocket server port field.
+## Server variants
+
+This app runs the Python Matter Server implementation from the
+[home-assistant-libs/python-matter-server][matter_server_repo] repository by default.
+
+Starting with version 8.2.0 and choosing the "Beta" flag (see below) the new OHF
+Matter(.js) Server is executed instead of the Python Matter Server.
+
## Configuration
-Add-on configuration:
+App configuration:
-| Configuration | Description |
-|--------------------|-------------------------------------------------------------|
-| log_level | Logging level of the Matter Server component. |
+| Configuration | Description |
+|----------------------|---------------------------------------------------------------------------------------------------------|
+| log_level | Logging level of the Matter Server component. |
+| log_level_sdk | Logging level for Matter SDK logs (Python only). |
+| beta | Whether to install the latest beta version on startup (runs matter.js-based Matter Server starting with 8.2.0) |
+| enable_test_net_dcl | Enable test-net DCL for PAA root certificates, OTA updates and other device information. |
+| bluetooth_adapter_id | Set BlueZ Bluetooth Controller ID (for local commissioning) |
## Support
diff --git a/matter_server/Dockerfile b/matter_server/Dockerfile
index 135f97efc13..7037b2b311b 100644
--- a/matter_server/Dockerfile
+++ b/matter_server/Dockerfile
@@ -33,6 +33,12 @@ RUN \
curl \
ca-certificates \
xz-utils \
+ bluez \
+ libbluetooth-dev \
+ libudev-dev \
+ make \
+ gcc \
+ g++ \
&& mkdir -p /usr/share/man/man1 \
\
&& if [ "${BUILD_ARCH}" = "armv7" ]; then \
@@ -69,6 +75,23 @@ RUN \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /usr/src/*
+# Install Node.js 22.x for JavaScript Matter Server (beta mode)
+# We download from nodejs.org instead of using OS packages to ensure
+# we have up-to-date Node.js versions with latest features and fixes
+ARG NODE_VERSION
+RUN \
+ set -x \
+ && DPKG_ARCH=$(dpkg --print-architecture) \
+ && case "${DPKG_ARCH}" in \
+ amd64) NODE_ARCH="x64" ;; \
+ *) NODE_ARCH="${DPKG_ARCH}" ;; \
+ esac \
+ && curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" -o /tmp/node.tar.xz \
+ && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 --no-same-owner \
+ && rm -f /tmp/node.tar.xz \
+ && node --version \
+ && npm --version
+
# S6-Overlay
WORKDIR /root
ENTRYPOINT ["/init"]
diff --git a/matter_server/README.md b/matter_server/README.md
index 1cab39a8791..3341b813a76 100644
--- a/matter_server/README.md
+++ b/matter_server/README.md
@@ -1,15 +1,16 @@
-# Home Assistant Add-on: Matter Server
+# Home Assistant App: Matter Server
![Supports aarch64 Architecture][aarch64-shield]
![Supports amd64 Architecture][amd64-shield]
## About
-Matter Python WebSocket Server for Home Assistant Core. Matter (formerly
-known as Connected Home over IP or CHIP) is an IPv6 based smart home
-standard. This add-on provides a Matter Controller which allows you to
-commission and control of Matter devices. The matching Home Assistant Core
-integration communicates via WebSocket with this server.
+Matter WebSocket Server for Home Assistant Core. Matter (formerly
+known as Connected Home over IP or CHIP) is an IPv6-based smart home
+standard. This app (formerly known as add-on) provides a
+Matter Controller which allows you to commission and control Matter
+devices. The matching Home Assistant Core integration communicates via
+WebSocket with this server.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
diff --git a/matter_server/RELEASE.md b/matter_server/RELEASE.md
index 66d639186dd..684d76a96e0 100644
--- a/matter_server/RELEASE.md
+++ b/matter_server/RELEASE.md
@@ -2,10 +2,10 @@
## Matter Server Update Procedure
-When updating the server library in the add-on follow these steps:
+When updating the server library in the app (formerly known as add-on) follow these steps:
1. Update the `MATTER_SERVER_VERSION` argument in `build.yaml`.
2. Check if the chip SDK version has changed in the server library.
-3. If the minimal supported schema version has changed, set the `homeassistant` key in `config.yaml` to the minimum version of Home Assistant Core required to install or update the add-on.
-4. Update the add-on version in `config.yaml`. Bump to a new major version if the minimum schema version has changed.
+3. If the minimal supported schema version has changed, set the `homeassistant` key in `config.yaml` to the minimum version of Home Assistant Core required to install or update the app.
+4. Update the app version in `config.yaml`. Bump to a new major version if the minimum schema version has changed.
5. Update the changelog in `CHANGELOG.md`. Include a markdown link to the GitHub release of the server in the changelog.
diff --git a/matter_server/build.yaml b/matter_server/build.yaml
index 18f233be010..89b5bebc8d3 100644
--- a/matter_server/build.yaml
+++ b/matter_server/build.yaml
@@ -1,8 +1,9 @@
---
build_from:
- aarch64: ghcr.io/home-assistant-libs/python-matter-server:5.8.1
- amd64: ghcr.io/home-assistant-libs/python-matter-server:5.8.1
+ aarch64: ghcr.io/matter-js/python-matter-server:8.1.2
+ amd64: ghcr.io/matter-js/python-matter-server:8.1.2
args:
- BASHIO_VERSION: 0.14.3
- TEMPIO_VERSION: 2021.09.0
- S6_OVERLAY_VERSION: 3.1.5.0
+ BASHIO_VERSION: 0.17.1
+ TEMPIO_VERSION: 2024.11.2
+ S6_OVERLAY_VERSION: 3.1.6.2
+ NODE_VERSION: 22.21.1
diff --git a/matter_server/config.yaml b/matter_server/config.yaml
index 1e2635abc85..564004e6f32 100644
--- a/matter_server/config.yaml
+++ b/matter_server/config.yaml
@@ -1,5 +1,5 @@
---
-version: 5.4.1
+version: 8.2.2
slug: matter_server
name: Matter Server
description: Matter WebSocket Server for Home Assistant Matter support.
@@ -11,21 +11,33 @@ arch:
discovery:
- matter
hassio_api: true
-homeassistant: 2023.12.0
+homeassistant: 2024.6.0
# IPC is only used within the Add-on
host_ipc: false
host_network: true
host_dbus: true
image: homeassistant/{arch}-addon-matter-server
+ingress: true
+ingress_port: 5580
init: false
+map:
+ - type: addon_config
+ read_only: false
options:
log_level: info
log_level_sdk: error
beta: false
+ enable_test_net_dcl: false
schema:
- log_level: list(debug|info|warning|error|critical)
+ log_level: list(verbose|debug|info|warning|error|critical)
log_level_sdk: list(automation|detail|progress|error|none)?
beta: bool?
+ enable_test_net_dcl: bool?
+ bluetooth_adapter_id: int?
+ matter_server_args:
+ - str?
+ matter_server_version: str?
+ matter_sdk_wheels_version: str?
ports:
5580/tcp: null
stage: stable
diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish
index 51f54f4173e..40aba91d0b4 100755
--- a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish
+++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish
@@ -1,4 +1,5 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run
index b3e142d2626..4f6c83c0480 100755
--- a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run
+++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start matter-server service
# ==============================================================================
@@ -8,6 +10,10 @@ declare server_port
declare log_level
declare log_level_sdk
declare primary_interface
+declare matter_server_version
+declare chip_version
+declare use_js_server
+matter_server_args=()
extra_args=()
if ! bashio::config.exists log_level; then
@@ -18,9 +24,43 @@ log_level=$(bashio::string.lower "$(bashio::config log_level info)")
# Make Matter SDK log level currently default to error
log_level_sdk=$(bashio::string.lower "$(bashio::config log_level_sdk error)")
-if bashio::config.true "beta"; then
- bashio::log.info 'Upgrading Python Matter Server to latest pre-release'
- pip3 install --upgrade --pre python-matter-server[server]
+# Determine server type based on beta flag
+use_js_server=$(bashio::config "beta")
+
+if [[ "${use_js_server}" == "true" ]]; then
+ # Beta mode: Use JavaScript Matter Server
+ bashio::log.info "Using JavaScript Matter Server (beta mode)"
+ bashio::log.info "Installing latest matter-server from npm..."
+ mkdir -p /opt/matterjs
+ # shellcheck disable=SC2164
+ cd /opt/matterjs
+ if ! npm install --foreground-scripts matter-server@latest; then
+ bashio::log.error "Failed to install Matter Server from npm. Aborting startup."
+ exit 1
+ fi
+ # Clean up to save disk space
+ npm cache clean --force
+ find ./node_modules -type d -name "cjs" -path "*/@matter/*" -exec rm -rf {} + 2>/dev/null || true
+ find ./node_modules -type d -name "cjs" -path "*/@project-chip/*" -exec rm -rf {} + 2>/dev/null || true
+ rm -rf /tmp/* /var/tmp/* /root/.npm /root/.cache 2>/dev/null || true
+else
+ # Non-beta mode: Use Python Matter Server
+ bashio::log.info "Using Python Matter Server"
+
+ if bashio::config.has_value "matter_server_version"; then
+ matter_server_version=$(bashio::config 'matter_server_version')
+ bashio::log.info "Installing Python Matter Server ${matter_server_version}"
+ # shellcheck disable=SC2102
+ pip3 install --pre python-matter-server[server]=="${matter_server_version}"
+ fi
+
+ if bashio::config.has_value "matter_sdk_wheels_version"; then
+ chip_version=$(bashio::config 'matter_sdk_wheels_version')
+ bashio::log.info "Installing Matter SDK ${chip_version}"
+ pip3 install --pre --no-dependencies \
+ home-assistant-chip-clusters=="${chip_version}" \
+ home-assistant-chip-core=="${chip_version}"
+ fi
fi
# Bind to internal hassio network only unless user requests to expose
@@ -30,33 +70,60 @@ if ! bashio::var.has_value "${server_port}"; then
extra_args+=('--listen-address' "$(bashio::addon.ip_address)")
fi
+if bashio::config.true "enable_test_net_dcl"; then
+ extra_args+=('--enable-test-net-dcl')
+fi
+
primary_interface="$(bashio::api.supervisor 'GET' '/network/info' '' 'first(.interfaces[] | select (.primary == true)) .interface')"
# Try fallback method (e.g. in case NetworkManager is not available)
+# shellcheck disable=SC2086
if [ -z ${primary_interface} ]; then
- bashio::log.warn 'Trying fallback method to determine primary interface'
+ bashio::log.warning 'Trying fallback method to determine primary interface'
primary_interface="$(ip --json route show default | jq --raw-output '.[0].dev')"
fi
+# shellcheck disable=SC2086
if [ -z ${primary_interface} ] || [ ${primary_interface} == "null" ]; then
bashio::exit.nok "No primary network interface found!"
fi
+if bashio::config.has_value "bluetooth_adapter_id"; then
+ # shellcheck disable=SC2207
+ extra_args+=('--bluetooth-adapter' $(bashio::config 'bluetooth_adapter_id'))
+fi
+
+if bashio::config.has_value "matter_server_args"; then
+ # shellcheck disable=SC2207
+ extra_args+=($(bashio::config 'matter_server_args'))
+fi
+
bashio::log.info "Using '${primary_interface}' as primary network interface."
# Send out discovery information to Home Assistant
/etc/s6-overlay/scripts/matter-server-discovery &
+# shellcheck disable=SC2164
cd /root
-if bashio::config.true "beta"; then
- exec /usr/bin/gdb --quiet -ex="set confirm off" -ex run -ex backtrace -ex "quit \$_exitcode" --args /usr/local/bin/python \
- /usr/local/bin/matter-server --storage-path "/data" --port "${server_port}" \
- --log-level "${log_level}" --primary-interface "${primary_interface}" \
- --fabricid 2 --vendorid 4939 "${extra_args[@]}"
+# shellcheck disable=SC2206
+matter_server_args+=(
+ '--storage-path' "/data"
+ '--port' "${server_port}"
+ '--log-level' "${log_level}"
+ '--log-level-sdk' "${log_level_sdk}"
+ '--primary-interface' "${primary_interface}"
+ '--paa-root-cert-dir' "/data/credentials"
+ '--ota-provider-dir' "/config/updates"
+ '--fabricid' 2
+ '--vendorid' 4939
+ ${extra_args[@]}
+)
+
+if [[ "${use_js_server}" == "true" ]]; then
+ # Start JavaScript Matter Server
+ exec node --enable-source-maps /opt/matterjs/node_modules/matter-server/dist/esm/MatterServer.js "${matter_server_args[@]}"
else
- exec /usr/local/bin/matter-server --storage-path "/data" --port "${server_port}" \
- --log-level "${log_level}" --log-level-sdk "${log_level_sdk}" \
- --primary-interface "${primary_interface}" \
- --fabricid 2 --vendorid 4939 "${extra_args[@]}"
+ # Start Python Matter Server
+ exec /usr/local/bin/matter-server "${matter_server_args[@]}"
fi
diff --git a/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh b/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh
index 37a8218fdf5..074dc4179e5 100755
--- a/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh
+++ b/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: Base Images
# Displays a simple add-on banner on startup
diff --git a/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery b/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery
index f37ea192617..d36992d8b2f 100755
--- a/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery
+++ b/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Send matter discovery information to Home Assistant
# ==============================================================================
diff --git a/matter_server/translations/en.yaml b/matter_server/translations/en.yaml
index c2613aca457..0cd532b6cc8 100644
--- a/matter_server/translations/en.yaml
+++ b/matter_server/translations/en.yaml
@@ -3,10 +3,48 @@ configuration:
log_level:
name: Matter Server Log Level
description: Logging level of the Matter Server component.
+ log_level_sdk:
+ name: Matter SDK Log Level
+ description: Logging level of the Matter SDK (Python only).
beta:
name: Use the latest beta version
description: >-
- Installs the latest beta of the Python Matter Server. It is recommended
- to create a backup before starting the add-on with this flag enabled!
+ Installs the latest beta of the Matter Server (matter.js based). It is
+ highly recommended to create a backup before starting the app with
+ this flag enabled!
+ enable_test_net_dcl:
+ name: Enable test-net DCL usage.
+ description: >-
+ Enable PAA root certificates, software updates and other device
+ information from test-net DCL. This is meant for development and testing
+ purposes.
+ bluetooth_adapter_id:
+ name: Bluetooth Adapter ID
+ description: >-
+ BlueZ Bluetooth Adapter Controller ID used by the Matter Server. This is
+ required if local commissioning via Bluetooth is used. Note: Using the
+ Home Assistant Companion app commissioning method is recommended as it is
+ better tested and allows to commission directly in proximity of the
+ device itself.
+ matter_server_args:
+ name: Extra Matter Server arguments
+ description: >-
+ This allows to pass additional command line arguments to the Matter
+ Server. Use `--help` to get a list of possible arguments. Note that
+ arguments are also added by the startup script controlled by other
+ app options.
+ matter_server_version:
+ name: Matter Server version
+ description: >-
+ Install custom Python Matter Server version (not applicable when using
+ Beta flag). WARNING: An older version might have an incompatible storage
+ format! Use this feature with caution! Make sure you have a recent backup
+ of the app!
+ matter_sdk_wheels_version:
+ name: Matter SDK wheels version
+ description: >-
+ Install custom Python Matter SDK wheels version (not applicable when
+ using Beta flag). NOTE: The API might not be compatible with the Python
+ Matter server.
network:
5580/tcp: Matter Server WebSocket server port.
diff --git a/mosquitto/CHANGELOG.md b/mosquitto/CHANGELOG.md
index 339cf8379ac..58c85fe8ded 100644
--- a/mosquitto/CHANGELOG.md
+++ b/mosquitto/CHANGELOG.md
@@ -1,5 +1,24 @@
# Changelog
+## 6.5.2
+
+- Update mosquitto to version 2.0.22
+
+## 6.5.1
+
+- Update mosquitto to version 2.0.21
+
+## 6.5.0
+
+- Update base image to Debian 12 (bookworm)
+- Update mosquitto to version 2.0.20
+- Update mosquitto-go-auth to version 2.1.0
+- Update libwebsockets to version 4.3.3
+
+## 6.4.1
+
+- Increase default max_queued_messages to 8192 to fix dropped messages during Home Assistant startup
+
## 6.4.0
- Update mosquitto to 2.0.18
@@ -14,7 +33,7 @@
## 6.2.1
-- Add explicit dependencies for dynamic security plugin and asynchronous name resolver
+- Add explicit dependencies for dynamic security plugin and asynchronous name resolver
## 6.2.0
@@ -41,7 +60,7 @@
Note: Mosquitto 2.0.0 did contain some breaking changes. We don't anticipate
most users to be affected by them but if you have a heavily customized mosquitto
-config we would advise reviewing [their changelog](https://mosquitto.org/ChangeLog.txt).
+config we would advise reviewing [their changelog](https://mosquitto.org/ChangeLog.txt).
## 6.0.2
diff --git a/mosquitto/DOCS.md b/mosquitto/DOCS.md
index d6c1feef5f4..954d800df71 100644
--- a/mosquitto/DOCS.md
+++ b/mosquitto/DOCS.md
@@ -1,22 +1,22 @@
-# Home Assistant Add-on: Mosquitto broker
+# Home Assistant App: Mosquitto broker
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Mosquitto broker" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Mosquitto broker" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The add-on has a couple of options available. To get the add-on running:
+The app has a couple of options available. To get the app running:
-1. Start the add-on.
+1. Start the app.
2. Have some patience and wait a couple of minutes.
-3. Check the add-on log output to see the result.
+3. Check the app log output to see the result.
-Create a new user for MQTT via your Home Assistant's frontend **Settings** -> **People** -> **Users** , (i.e. not on Mosquitto's **Configuration** tab).
+Create a new user for MQTT via your Home Assistant's frontend **Settings** > **People** > **Users** , (i.e. not on Mosquitto's **Configuration** tab).
Notes:
1. This name cannot be `homeassistant` or `addons`, those are reserved usernames.
@@ -24,7 +24,7 @@ Notes:
To use the Mosquitto as a broker, go to the integration page and install the configuration with one click:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Devices & Services** -> **Integrations**.
+1. Navigate in your Home Assistant frontend to **Settings** > **Devices & Services** > **Integrations**.
2. MQTT should appear as a discovered integration at the top of the page
3. Select it and check the box to enable MQTT discovery if desired, and hit submit.
@@ -32,7 +32,7 @@ If you have old MQTT settings available, remove this old integration and restart
## Configuration
-Add-on configuration:
+App configuration:
```yaml
logins: []
@@ -68,6 +68,8 @@ logins:
password_pre_hashed: true
```
+**Note:** This app does not support anonymous logins; all connections must use a username/password to connect. `allow_anonymous true` nor any anonymous ACLs will not work with this app.
+
#### Option: `customize.active`
If set to `true` additional configuration files will be read, see the next option.
@@ -86,24 +88,24 @@ A file containing a root certificate. Place this file in the Home Assistant `ssl
A file containing a certificate, including its chain. Place this file in the Home Assistant `ssl` folder.
-**Note on `certfile` and `keyfile`**
+**Note on `certfile` and `keyfile`**
- If `certfile` and `keyfile` are _not_ provided
- Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets)
- If `certfile` and `keyfile` are provided
- Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets)
- - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets)
+ - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets)
- In that case, the client must trust the server's certificate
### Option: `keyfile`
A file containing the private key. Place this file in the Home Assistant `ssl` folder.
-**Note on `certfile` and `keyfile`**
+**Note on `certfile` and `keyfile`**
- If `certfile` and `keyfile` are _not_ provided
- Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets)
- If `certfile` and `keyfile` are provided
- Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets)
- - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets)
+ - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets)
- In that case, the client must trust the server's certificate
### Option: `require_certificate`
@@ -123,11 +125,11 @@ If set to `true` turns on debug logging for mosquitto and its auth plugin. This
## Home Assistant user management
-This add-on is attached to the Home Assistant user system, so MQTT clients can make use of these credentials. Local users may also still be set independently within the configuration options for the add-on. For the internal Home Assistant ecosystem, we register `homeassistant` and `addons`, so these may not be used as user names.
+This app is attached to the Home Assistant user system, so MQTT clients can make use of these credentials. Local users may also still be set independently within the configuration options for the app. For the internal Home Assistant ecosystem, we register `homeassistant` and `addons`, so these may not be used as user names.
## Disable listening on insecure (1883/1884) ports
-Remove the ports from the add-on page network card (set them as blank) to disable them.
+Remove the ports from the app page network card (set them as blank) to disable them.
### Access Control Lists (ACLs)
@@ -161,10 +163,10 @@ Add the following configuration to enable **unrestricted** access to all topics
```text
user addons
topic readwrite #
-
+
user homeassistant
topic readwrite #
-
+
user [YOUR_MQTT_USER]
topic readwrite #
```
diff --git a/mosquitto/Dockerfile b/mosquitto/Dockerfile
index d49c0e02782..5de4082485a 100644
--- a/mosquitto/Dockerfile
+++ b/mosquitto/Dockerfile
@@ -24,18 +24,21 @@ RUN apt-get update \
golang-go \
\
# Compile and install libwebsocket
- && git clone --depth 1 -b "${LIBWEBSOCKET_VERSION}" \
+ #
+ # DLWS_WITHOUT_TESTAPPS is just a workaround, see
+ # https://github.com/warmcat/libwebsockets/issues/2790 for more
+ && git clone --depth 1 -b "v${LIBWEBSOCKET_VERSION}" \
https://libwebsockets.org/repo/libwebsockets \
\
&& cd libwebsockets \
&& mkdir build \
&& cd build \
- && cmake -DLWS_WITH_EXTERNAL_POLL=ON .. \
+ && cmake -DLWS_WITH_EXTERNAL_POLL=ON -DLWS_WITHOUT_TESTAPPS=ON .. \
&& make install \
&& ldconfig \
&& cd ../.. \
# Compile and install mosquitto
- && git clone --depth 1 -b "${MOSQUITTO_VERSION}" \
+ && git clone --depth 1 -b "v${MOSQUITTO_VERSION}" \
https://github.com/eclipse/mosquitto \
\
&& cd mosquitto \
diff --git a/mosquitto/README.md b/mosquitto/README.md
index 6edd8ed9423..0b98694d30a 100644
--- a/mosquitto/README.md
+++ b/mosquitto/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: Mosquitto broker
+# Home Assistant App: Mosquitto broker
MQTT broker for Home Assistant.
@@ -6,7 +6,7 @@ MQTT broker for Home Assistant.
## About
-You can use this add-on to install Eclipse Mosquitto, which is an open-source (EPL/EDL licensed) message broker that implements the MQTT protocol. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers. For more information, please see [mosquitto].
+You can use this app (formerly known as add-on) to install Eclipse Mosquitto, which is an open-source (EPL/EDL licensed) message broker that implements the MQTT protocol. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers. For more information, please see [mosquitto].
[mosquitto]: https://mosquitto.org
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/mosquitto/build.yaml b/mosquitto/build.yaml
index 8f068d11c38..dc5ac449067 100644
--- a/mosquitto/build.yaml
+++ b/mosquitto/build.yaml
@@ -1,14 +1,11 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base-debian:bullseye
- amd64: ghcr.io/home-assistant/amd64-base-debian:bullseye
- armhf: ghcr.io/home-assistant/armhf-base-debian:bullseye
- armv7: ghcr.io/home-assistant/armv7-base-debian:bullseye
- i386: ghcr.io/home-assistant/i386-base-debian:bullseye
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
+ amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
+ armhf: ghcr.io/home-assistant/armhf-base-debian:bookworm
+ armv7: ghcr.io/home-assistant/armv7-base-debian:bookworm
+ i386: ghcr.io/home-assistant/i386-base-debian:bookworm
args:
- LIBWEBSOCKET_VERSION: v4.3.2
- MOSQUITTO_VERSION: v2.0.18
- MOSQUITTO_AUTH_VERSION: 1.8.2
+ LIBWEBSOCKET_VERSION: 4.3.3
+ MOSQUITTO_VERSION: 2.0.22
+ MOSQUITTO_AUTH_VERSION: 2.1.0
diff --git a/mosquitto/config.yaml b/mosquitto/config.yaml
index 986fab1bc5c..ceb572884bf 100644
--- a/mosquitto/config.yaml
+++ b/mosquitto/config.yaml
@@ -1,10 +1,9 @@
---
-version: 6.4.0
+version: 6.5.2
slug: mosquitto
name: Mosquitto broker
description: An Open Source MQTT broker
url: https://github.com/home-assistant/addons/tree/master/mosquitto
-codenotary: notary@home-assistant.io
arch:
- armhf
- armv7
diff --git a/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh b/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh
index 3882775b2ce..3a0600d8634 100755
--- a/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh
+++ b/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Configures mosquitto
# ==============================================================================
diff --git a/mosquitto/rootfs/etc/cont-init.d/nginx.sh b/mosquitto/rootfs/etc/cont-init.d/nginx.sh
index e4a4a5126f6..25dcfa5d6b8 100755
--- a/mosquitto/rootfs/etc/cont-init.d/nginx.sh
+++ b/mosquitto/rootfs/etc/cont-init.d/nginx.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Configures NGINX
# ==============================================================================
diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/discovery b/mosquitto/rootfs/etc/services.d/mosquitto/discovery
index 0f45fda3c89..6f330537dbf 100755
--- a/mosquitto/rootfs/etc/services.d/mosquitto/discovery
+++ b/mosquitto/rootfs/etc/services.d/mosquitto/discovery
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Send MQTT discovery information to Home Assistant and service information
# to the Supervisor (for other add-ons).
diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/finish b/mosquitto/rootfs/etc/services.d/mosquitto/finish
index 5a23d05348c..f4c53b282d0 100755
--- a/mosquitto/rootfs/etc/services.d/mosquitto/finish
+++ b/mosquitto/rootfs/etc/services.d/mosquitto/finish
@@ -1,4 +1,5 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/run b/mosquitto/rootfs/etc/services.d/mosquitto/run
index f25b2bc495b..79e114469ef 100755
--- a/mosquitto/rootfs/etc/services.d/mosquitto/run
+++ b/mosquitto/rootfs/etc/services.d/mosquitto/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Runs mosquitto
# ==============================================================================
diff --git a/mosquitto/rootfs/etc/services.d/nginx/finish b/mosquitto/rootfs/etc/services.d/nginx/finish
index 5a23d05348c..f4c53b282d0 100755
--- a/mosquitto/rootfs/etc/services.d/nginx/finish
+++ b/mosquitto/rootfs/etc/services.d/nginx/finish
@@ -1,4 +1,5 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
diff --git a/mosquitto/rootfs/etc/services.d/nginx/run b/mosquitto/rootfs/etc/services.d/nginx/run
index a585b2ba91c..b433b18d5bd 100755
--- a/mosquitto/rootfs/etc/services.d/nginx/run
+++ b/mosquitto/rootfs/etc/services.d/nginx/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Runs the NGINX daemon
# ==============================================================================
diff --git a/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl b/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl
index c484bf8141d..c1a840461c9 100644
--- a/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl
+++ b/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl
@@ -13,6 +13,12 @@ log_timestamp_format %Y-%m-%d %H:%M:%S
persistence true
persistence_location /data/
+# Limits
+# max_queued_messages is effectively the upper limit of
+# the number of entities on Home Assistant if startup
+# is busy and cannot read messages fast enough
+max_queued_messages 8192
+
# Authentication plugin
auth_plugin /usr/share/mosquitto/go-auth.so
auth_opt_backends files,http
diff --git a/nginx_proxy/CHANGELOG.md b/nginx_proxy/CHANGELOG.md
index 56395169df1..7006582fb22 100644
--- a/nginx_proxy/CHANGELOG.md
+++ b/nginx_proxy/CHANGELOG.md
@@ -1,5 +1,43 @@
# Changelog
+## 4.0.0
+
+- Drop builds of unsupported architectures
+- Update base image to Alpine 3.23 (base image tag 3.23-2025.12.2)
+
+## 3.15.0
+
+- Support HTTP/3 (QUIC)
+
+## 3.14.0
+
+- Listen over IPv6, since true IPv6 support for add-ons is now available
+
+## 3.13.0
+
+- Update Alpine Linux to 3.22 (nginx 1.28.x)
+- Update to current Mozilla intermediate SSL config
+
+## 3.12.0
+
+- Add origin and X-Forwarded-Proto headers to fix origin issues affecting Portainer and other addons
+
+## 3.11.1
+
+- Update to new nginx http2 directive. This also suppress a deprecation warning.
+
+## 3.11.0
+
+- Update Alpine Linux to 3.20 (nginx 1.26.x)
+
+## 3.10.1
+
+- Make `real_ip_from` optional through an empty default value
+
+## 3.10.0
+
+- Supporting TCP Proxy Protocol
+
## 3.9.0
- Add `map_hash_bucket_size` to add support for longer matches in `map`
@@ -11,7 +49,7 @@
## 3.7.0
- Modify `server_names_hash_bucket_size` to add support for longer domain names
-
+
## 3.6.0
- Add port to Host header to fix origin issues affecting ESPHome and other addons
diff --git a/nginx_proxy/DOCS.md b/nginx_proxy/DOCS.md
index 46abf8f1153..a1d7b856780 100644
--- a/nginx_proxy/DOCS.md
+++ b/nginx_proxy/DOCS.md
@@ -1,16 +1,16 @@
-# Home Assistant Add-on: NGINX Home Assistant SSL proxy
+# Home Assistant App: NGINX Home Assistant SSL proxy
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "NGINX Home Assistant SSL proxy" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "NGINX Home Assistant SSL proxy" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The NGINX Proxy add-on is commonly used in conjunction with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) and/or the [Let's Encrypt](https://github.com/home-assistant/addons/tree/master/letsencrypt) add-on to set up secure remote access to your Home Assistant instance. The following instructions covers this scenario.
+The NGINX Proxy app is commonly used in conjunction with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) and/or the [Let's Encrypt](https://github.com/home-assistant/addons/tree/master/letsencrypt) app to set up secure remote access to your Home Assistant instance. The following instructions covers this scenario.
1. The certificate to your registered domain should already be created via [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns), [Let's Encrypt](https://github.com/home-assistant/addons/tree/master/letsencrypt) or another method. Make sure that the certificate files exist in the `/ssl` directory.
2. You must add the following section to your [Home Assistant configuration.yaml](https://www.home-assistant.io/docs/configuration/). If the `http` section is using the `ssl_certificate`, `ssl_key` or `server_port` keys, make sure to remove them.
@@ -21,17 +21,17 @@ The NGINX Proxy add-on is commonly used in conjunction with the [Duck DNS](https
trusted_proxies:
- 172.30.33.0/24
```
-3. In the nginx addon configuration, change the `domain` option to the domain name you registered (from DuckDNS or any other domain you control).
+3. In the nginx app configuration, change the `domain` option to the domain name you registered (from DuckDNS or any other domain you control).
4. Leave all other options as-is.
5. Save configuration.
-6. Start the add-on.
+6. Start the app.
7. Have some patience and wait a couple of minutes.
-8. Check the add-on log output to see the result.
+8. Check the app log output to see the result.
## Configuration
-Add-on configuration:
+App configuration:
```yaml
domain: home.example.com
@@ -43,6 +43,7 @@ customize:
default: "nginx_proxy_default*.conf"
servers: "nginx_proxy/*.conf"
cloudflare: false
+real_ip_from: []
```
### Option: `domain` (required)
@@ -51,7 +52,7 @@ The server's fully qualified domain name to use for the proxy.
### Option: `certfile` (required)
-The certificate file to use in the `/ssl` directory. Keep filename as-is if you used default settings to create the certificate with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) add-on.
+The certificate file to use in the `/ssl` directory. Keep filename as-is if you used default settings to create the certificate with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) app.
### Option: `keyfile` (required)
@@ -78,13 +79,22 @@ The filename(s) of the NGINX configuration for the additional servers, found in
If enabled, configure Nginx with a list of IP addresses directly from Cloudflare that will be used for `set_real_ip_from` directive Nginx config.
This is so the `ip_ban_enabled` feature can be used and work correctly in /config/customize.yaml.
+### Option `real_ip_from` (optional)
+
+If specified, configures Nginx to use Proxy Protocol to get the Real Ip from an upstream load balancer; [for more information](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/).
+
+### Port `HTTP/3 (QUIC)` (optional)
+
+If specified, configures Nginx to use HTTP/3 with QUIC/UDP on this UDP port in addition to HTTP/2 and HTTP/1.1 on the TCP port; [for more information](https://nginx.org/en/docs/http/ngx_http_v3_module.html).
+
## Known issues and limitations
-- By default, port 80 is disabled in the add-on configuration in case the port is needed for other components or add-ons like `emulated_hue`.
+- By default, port 80 is disabled in the app configuration in case the port is needed for other components or apps like `emulated_hue`.
## Troubleshooting
- `400 Bad Request` response for requests over this proxy mean you are probably missing the `trusted_proxies` configuration option, see above.
+- HTTP/3 (QUIC) enabled, but not working. Check for the `Alt-Svc 'h3=":443"; ma=86400'` header in your web browser's development tools. Make sure the UDP QUIC port is forwarded or allowed in your firewall, in addition to the TCP HTTPS port.
## Support
diff --git a/nginx_proxy/README.md b/nginx_proxy/README.md
index c43bcc05b87..82d00b05efc 100644
--- a/nginx_proxy/README.md
+++ b/nginx_proxy/README.md
@@ -1,18 +1,14 @@
-# Home Assistant Add-on: NGINX Home Assistant SSL proxy
+# Home Assistant App: NGINX Home Assistant SSL proxy
Sets up an SSL proxy with NGINX and redirects traffic from port 80 to 443.
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
## About
Sets up an SSL proxy with NGINX web server. It is typically used to forward SSL internet traffic while allowing unencrypted local traffic to/from a Home Assistant instance.
-Make sure you have generated a certificate before you start this add-on. The [Duck DNS](https://github.com/home-assistant/hassio-addons/tree/master/duckdns) add-on can generate a Let's Encrypt certificate that can be used by this add-on.
+Make sure you have generated a certificate before you start this app. The [Duck DNS](https://github.com/home-assistant/hassio-addons/tree/master/duckdns) app can generate a Let's Encrypt certificate that can be used by this app.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
-[discord]: https://discord.gg/c5DvZ4e
diff --git a/nginx_proxy/build.yaml b/nginx_proxy/build.yaml
index 039821f92e6..2150ff5d109 100644
--- a/nginx_proxy/build.yaml
+++ b/nginx_proxy/build.yaml
@@ -1,10 +1,4 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armhf: ghcr.io/home-assistant/armhf-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.23-2025.12.2
+ amd64: ghcr.io/home-assistant/amd64-base:3.23-2025.12.2
diff --git a/nginx_proxy/config.yaml b/nginx_proxy/config.yaml
index ae567d2e689..f4db51c5a8b 100644
--- a/nginx_proxy/config.yaml
+++ b/nginx_proxy/config.yaml
@@ -1,16 +1,13 @@
---
-version: 3.9.0
+version: 4.0.0
hassio_api: true
slug: nginx_proxy
name: NGINX Home Assistant SSL proxy
description: An SSL/TLS proxy
url: https://github.com/home-assistant/addons/tree/master/nginx_proxy
arch:
- - armhf
- - armv7
- aarch64
- amd64
- - i386
image: homeassistant/{arch}-addon-nginx_proxy
init: false
map:
@@ -26,8 +23,10 @@ options:
active: false
default: nginx_proxy_default*.conf
servers: nginx_proxy/*.conf
+ real_ip_from: []
ports:
443/tcp: 443
+ 443/udp: null
80/tcp: null
schema:
domain: str
@@ -39,3 +38,5 @@ schema:
active: bool
default: str
servers: str
+ real_ip_from:
+ - str
diff --git a/nginx_proxy/rootfs/etc/nginx.conf b/nginx_proxy/rootfs/etc/nginx.conf
deleted file mode 100644
index 93cf43e7498..00000000000
--- a/nginx_proxy/rootfs/etc/nginx.conf
+++ /dev/null
@@ -1,76 +0,0 @@
-daemon off;
-error_log stderr;
-pid /var/run/nginx.pid;
-
-events {
- worker_connections 1024;
-}
-
-http {
- map_hash_bucket_size 128;
-
- map $http_upgrade $connection_upgrade {
- default upgrade;
- '' close;
- }
-
- server_tokens off;
-
- server_names_hash_bucket_size 128;
-
- # intermediate configuration
- ssl_protocols TLSv1.2 TLSv1.3;
- ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
- ssl_prefer_server_ciphers off;
-
- #include /data/cloudflare.conf;
-
- server {
- server_name _;
- listen 80 default_server;
- listen 443 ssl http2 default_server;
- ssl_reject_handshake on;
- return 444;
- }
-
- server {
- server_name %%DOMAIN%%;
-
- # These shouldn't need to be changed
- listen 80;
- return 301 https://$host$request_uri;
- }
-
- server {
- server_name %%DOMAIN%%;
-
- ssl_session_timeout 1d;
- ssl_session_cache shared:MozSSL:10m;
- ssl_session_tickets off;
- ssl_certificate /ssl/%%FULLCHAIN%%;
- ssl_certificate_key /ssl/%%PRIVKEY%%;
-
- # dhparams file
- ssl_dhparam /data/dhparams.pem;
-
- listen 443 ssl http2;
- %%HSTS%%
-
- proxy_buffering off;
-
- #include /share/nginx_proxy_default*.conf;
-
- location / {
- proxy_pass http://homeassistant.local.hass.io:%%HA_PORT%%;
- proxy_set_header Host $http_host;
- proxy_redirect http:// https://;
- proxy_http_version 1.1;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
- proxy_set_header X-Forwarded-Host $http_host;
- }
- }
-
- #include /share/nginx_proxy/*.conf;
-}
diff --git a/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl b/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl
new file mode 100644
index 00000000000..01a3ee890d1
--- /dev/null
+++ b/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl
@@ -0,0 +1,133 @@
+{{/*
+ Options saved in the Home Assistant UI are available in .options
+ Some variables are available in .variables, these are added in nginx/run
+*/}}
+daemon off;
+error_log stderr;
+pid /var/run/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ map_hash_bucket_size 128;
+
+ map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+ }
+
+ server_tokens off;
+
+ server_names_hash_bucket_size 128;
+
+ # intermediate configuration
+ # https://ssl-config.mozilla.org/#server=nginx&version=1.28.0&config=intermediate&openssl=3.5.0
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ecdh_curve X25519:prime256v1:secp384r1;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
+ ssl_prefer_server_ciphers off;
+
+ {{- if .options.cloudflare }}
+ include /data/cloudflare.conf;
+ {{- end }}
+
+ server {
+ server_name _;
+ listen 80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:80 default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+ {{- if .variables.quic_port }}
+ listen 443 quic reuseport default_server;
+ listen [::]:443 quic reuseport default_server;
+ http3 on;
+ {{- end }}
+ ssl_reject_handshake on;
+ return 444;
+ }
+
+ server {
+ server_name {{ .options.domain }};
+
+ # These shouldn't need to be changed
+ listen 80;
+ listen [::]:80;
+ return 301 https://$host$request_uri;
+ }
+
+ server {
+ server_name {{ .options.domain }};
+
+ ssl_session_timeout 1d;
+ ssl_session_cache shared:MozSSL:10m;
+ ssl_session_tickets off;
+ ssl_certificate /ssl/{{ .options.certfile }};
+ ssl_certificate_key /ssl/{{ .options.keyfile }};
+
+ # dhparams file
+ ssl_dhparam /data/dhparams.pem;
+
+ {{- if not .options.real_ip_from }}
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ http2 on;
+ {{- if .variables.quic_port }}
+ listen 443 quic;
+ listen [::]:443 quic;
+ http3 on;
+ {{- end }}
+ {{- else }}
+ listen 443 ssl proxy_protocol;
+ listen [::]:443 ssl proxy_protocol;
+ http2 on;
+ {{- if .variables.quic_port }}
+ listen 443 quic proxy_protocol;
+ listen [::]:443 quic proxy_protocol;
+ http3 on;
+ {{- end }}
+ {{- range .options.real_ip_from }}
+ set_real_ip_from {{.}};
+ {{- end }}
+ real_ip_header proxy_protocol;
+ {{- end }}
+
+ {{- if .variables.quic_port }}
+ add_header Alt-Svc 'h3=":{{ .variables.quic_port }}"; ma=86400';
+ {{- end }}
+
+ {{- if .options.hsts }}
+ add_header Strict-Transport-Security "{{ .options.hsts }}" always;
+ {{- end }}
+
+ proxy_buffering off;
+
+ {{- if .options.customize.active }}
+ include /share/{{ .options.customize.default }};
+ {{- end }}
+
+ location / {
+ proxy_pass http://homeassistant.local.hass.io:{{ .variables.port }};
+ proxy_set_header Origin $http_origin;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Host $http_host;
+ proxy_redirect http:// https://;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header X-Forwarded-Host $http_host;
+ {{- if not .options.real_ip_from }}
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ {{- else }}
+ proxy_set_header X-Real-IP $proxy_protocol_addr;
+ proxy_set_header X-Forwarded-For $proxy_protocol_addr;
+ {{- end }}
+ }
+ }
+
+ {{- if .options.customize.active }}
+ include /share/{{ .options.customize.servers }};
+ {{- end }}
+}
diff --git a/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal b/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal
index 120fbfca60d..95da6ff7044 100755
--- a/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal
+++ b/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal
@@ -1,4 +1,6 @@
#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Check certificate renewal
# ==============================================================================
diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish
index 955dc164ebf..c24c56f2dfd 100644
--- a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish
+++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish
@@ -1,9 +1,10 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when daemon fails
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run
index 5e683ce3aea..a97b8f4bf73 100644
--- a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run
+++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start crond service
diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
index 3a4cedbd8ac..4a4c070f1bb 100644
--- a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
+++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
@@ -1,9 +1,10 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when daemon fails
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
index 9f45483a9b7..471a2d9c7f9 100644
--- a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
+++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start nginx service
@@ -6,16 +7,24 @@
set -e
-DHPARAMS_PATH=/data/dhparams.pem
+QUIC_PORT="$(bashio::addon.port '443/udp')"
+if [[ -z "$QUIC_PORT" ]]; then
+ QUIC_PORT=null
+fi
-CLOUDFLARE_CONF=/data/cloudflare.conf
+bashio::log.info "Merging options & variables for template"
+JSON_CONF=$(jq --argjson port "$(bashio::core.port)" --argjson quic_port "$QUIC_PORT" \
+ '({options: .}) + ({variables: {port: $port, quic_port: $quic_port}})' \
+ /data/options.json)
+bashio::log.info "Generating nginx.conf from template in /etc/nginx/nginx.conf.gtpl"
+# shellcheck disable=SC2086
+echo $JSON_CONF | tempio \
+ -template /etc/nginx/nginx.conf.gtpl \
+ -out /etc/nginx.conf
-DOMAIN=$(bashio::config 'domain')
-KEYFILE=$(bashio::config 'keyfile')
-CERTFILE=$(bashio::config 'certfile')
-HSTS=$(bashio::config 'hsts')
+DHPARAMS_PATH=/data/dhparams.pem
-HA_PORT=$(bashio::core.port)
+CLOUDFLARE_CONF=/data/cloudflare.conf
# Generate dhparams
if ! bashio::fs.file_exists "${DHPARAMS_PATH}"; then
@@ -24,7 +33,6 @@ if ! bashio::fs.file_exists "${DHPARAMS_PATH}"; then
fi
if bashio::config.true 'cloudflare'; then
- sed -i "s|#include /data/cloudflare.conf;|include /data/cloudflare.conf;|" /etc/nginx.conf
# Generate cloudflare.conf
if ! bashio::fs.file_exists "${CLOUDFLARE_CONF}"; then
bashio::log.info "Creating 'cloudflare.conf' for real visitor IP address..."
@@ -47,24 +55,7 @@ if bashio::config.true 'cloudflare'; then
fi
fi
-# Prepare config file
-sed -i "s#%%FULLCHAIN%%#$CERTFILE#g" /etc/nginx.conf
-sed -i "s#%%PRIVKEY%%#$KEYFILE#g" /etc/nginx.conf
-sed -i "s/%%DOMAIN%%/$DOMAIN/g" /etc/nginx.conf
-sed -i "s/%%HA_PORT%%/$HA_PORT/g" /etc/nginx.conf
-
-[ -n "$HSTS" ] && HSTS="add_header Strict-Transport-Security \"$HSTS\" always;"
-sed -i "s/%%HSTS%%/$HSTS/g" /etc/nginx.conf
-
-# Allow customize configs from share
-if bashio::config.true 'customize.active'; then
- CUSTOMIZE_DEFAULT=$(bashio::config 'customize.default')
- sed -i "s|#include /share/nginx_proxy_default.*|include /share/$CUSTOMIZE_DEFAULT;|" /etc/nginx.conf
- CUSTOMIZE_SERVERS=$(bashio::config 'customize.servers')
- sed -i "s|#include /share/nginx_proxy/.*|include /share/$CUSTOMIZE_SERVERS;|" /etc/nginx.conf
-fi
-
# start server
bashio::log.info "Running nginx..."
-stat "/ssl/${CERTFILE}" -c %y > /tmp/certificate_timestamp
+stat "/ssl/$(bashio::config 'certfile')" -c %y > /tmp/certificate_timestamp
exec nginx -c /etc/nginx.conf < /dev/null
diff --git a/nginx_proxy/translations/en.yaml b/nginx_proxy/translations/en.yaml
index d75468cd3b4..c37045b0638 100644
--- a/nginx_proxy/translations/en.yaml
+++ b/nginx_proxy/translations/en.yaml
@@ -24,6 +24,12 @@ configuration:
name: Customize
description: >-
See the Documentation tab for more information about these options.
+ real_ip_from:
+ name: Real IP from (enables PROXY protocol)
+ description: >-
+ Configures Nginx to use TCP Proxy Protocol,
+ specifies what IP to trust TLS upstream requests from.
network:
443/tcp: HTTPS (SSL) Port
+ 443/udp: HTTP/3 (QUIC) Port, set to same as HTTPS (SSL) port to enable HTTP/3
80/tcp: HTTP (non-SSL) Port
diff --git a/openthread_border_router/0001-Avoid-writing-to-system-console.patch b/openthread_border_router/0001-Avoid-writing-to-system-console.patch
deleted file mode 100644
index 5536ca66c90..00000000000
--- a/openthread_border_router/0001-Avoid-writing-to-system-console.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From e0792b7605e6d6cb2ebd491025aee7f84d1edbaa Mon Sep 17 00:00:00 2001
-Message-ID:
-From: Stefan Agner
-Date: Thu, 17 Feb 2022 22:57:16 +0100
-Subject: [PATCH] Avoid writing to system console
-
-Add-ons do not have a working syslog infrastructure. The LOG_CONS
-options causes syslog() calls to log to the system console
-(/dev/console). Avoid writing to system console as we use logging to
-stderr.
----
- src/common/logging.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/common/logging.cpp b/src/common/logging.cpp
-index 5a787e8213..79fccf77ca 100644
---- a/src/common/logging.cpp
-+++ b/src/common/logging.cpp
-@@ -88,7 +88,7 @@ void otbrLogInit(const char *aProgramName, otbrLogLevel aLevel, bool aPrintStder
- ident = strrchr(aProgramName, '/');
- ident = (ident != nullptr) ? ident + 1 : aProgramName;
-
-- openlog(ident, (LOG_CONS | LOG_PID) | (aPrintStderr ? LOG_PERROR : 0), OTBR_SYSLOG_FACILITY_ID);
-+ openlog(ident, LOG_PID | (aPrintStderr ? LOG_PERROR : 0), OTBR_SYSLOG_FACILITY_ID);
- sLevel = aLevel;
- sDefaultLevel = sLevel;
- }
---
-2.42.0
-
diff --git a/openthread_border_router/0001-channel-monitor-disable-by-default.patch b/openthread_border_router/0001-channel-monitor-disable-by-default.patch
index 84dee6dce33..702ecd13cfd 100644
--- a/openthread_border_router/0001-channel-monitor-disable-by-default.patch
+++ b/openthread_border_router/0001-channel-monitor-disable-by-default.patch
@@ -1,5 +1,4 @@
-From f84792cd229e9c3c4f5921cf92d280810dc56716 Mon Sep 17 00:00:00 2001
-Message-ID:
+From 2d67b5d8d711e61551a28cac522484fd5cbc4982 Mon Sep 17 00:00:00 2001
From: Stefan Agner
Date: Sun, 7 Jan 2024 00:35:53 +0100
Subject: [PATCH] [channel-monitor] disable by default
@@ -29,5 +28,5 @@ index 8e6848832..c79660de8 100644
mIsUp = true;
--
-2.43.0
+2.45.2
diff --git a/openthread_border_router/0002-rest-support-deleting-the-dataset.patch b/openthread_border_router/0002-rest-support-deleting-the-dataset.patch
deleted file mode 100644
index f92d332ce60..00000000000
--- a/openthread_border_router/0002-rest-support-deleting-the-dataset.patch
+++ /dev/null
@@ -1,126 +0,0 @@
-From 2c0c78e5f4dc85a63934fc0c32c035a9c5b5babd Mon Sep 17 00:00:00 2001
-Message-ID: <2c0c78e5f4dc85a63934fc0c32c035a9c5b5babd.1692864566.git.stefan@agner.ch>
-In-Reply-To:
-References:
-From: Stefan Agner
-Date: Mon, 5 Jun 2023 23:41:50 +0200
-Subject: [PATCH] [rest] support deleting the dataset
-
-Add REST API to support deleting the active or pending operational
-dataset. Deleting the active operational dataset requires the Thread
-network to be disabled (just like modifying the active operational
-dataset). Subsequent use of the PUT method allows to build entirly
-new datasets with values generated by the stack (through
-otDatasetCreateNewNetwork).
----
- src/rest/openapi.yaml | 21 +++++++++++++++++++++
- src/rest/resource.cpp | 35 +++++++++++++++++++++++++++++++++++
- src/rest/resource.hpp | 1 +
- 3 files changed, 57 insertions(+)
-
-diff --git a/src/rest/openapi.yaml b/src/rest/openapi.yaml
-index 2ba2a4dd56..2edc4af29a 100644
---- a/src/rest/openapi.yaml
-+++ b/src/rest/openapi.yaml
-@@ -248,6 +248,18 @@ paths:
- description: Invalid request body.
- "409":
- description: Writing active operational dataset rejected because Thread network is active.
-+ delete:
-+ tags:
-+ - node
-+ summary: Deletes the active operational dataset
-+ description: |-
-+ Deletes the the active operational dataset on the current node. Only allowed if the Thread node
-+ is inactive.
-+ responses:
-+ "200":
-+ description: Successfully deleted the active operational dataset.
-+ "409":
-+ description: Deleting active operational dataset rejected because Thread network is active.
- /node/dataset/pending:
- get:
- tags:
-@@ -291,6 +303,15 @@ paths:
- description: Successfully created the pending operational dataset.
- "400":
- description: Invalid request body.
-+ delete:
-+ tags:
-+ - node
-+ summary: Deletes the pending operational dataset
-+ description: |-
-+ Deletes the the pending operational dataset on the current node.
-+ responses:
-+ "200":
-+ description: Successfully deleted the active operational dataset.
- components:
- schemas:
- LeaderData:
-diff --git a/src/rest/resource.cpp b/src/rest/resource.cpp
-index a60e9d9483..829835341a 100644
---- a/src/rest/resource.cpp
-+++ b/src/rest/resource.cpp
-@@ -767,12 +767,47 @@ exit:
- }
- }
-
-+void Resource::DeleteDataset(DatasetType aDatasetType, Response &aResponse) const
-+{
-+ otbrError error = OTBR_ERROR_NONE;
-+ std::string errorCode = GetHttpStatus(HttpStatusCode::kStatusOk);
-+ otOperationalDatasetTlvs datasetTlvs = {};
-+
-+ if (aDatasetType == DatasetType::kActive)
-+ {
-+ VerifyOrExit(otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_DISABLED, error = OTBR_ERROR_INVALID_STATE);
-+ }
-+
-+ if (aDatasetType == DatasetType::kActive)
-+ {
-+ VerifyOrExit(otDatasetSetActiveTlvs(mInstance, &datasetTlvs) == OT_ERROR_NONE, error = OTBR_ERROR_REST);
-+ }
-+ else if (aDatasetType == DatasetType::kPending)
-+ {
-+ VerifyOrExit(otDatasetSetPendingTlvs(mInstance, &datasetTlvs) == OT_ERROR_NONE, error = OTBR_ERROR_REST);
-+ }
-+ aResponse.SetResponsCode(errorCode);
-+
-+exit:
-+ if (error == OTBR_ERROR_INVALID_STATE)
-+ {
-+ ErrorHandler(aResponse, HttpStatusCode::kStatusConflict);
-+ }
-+ else if (error != OTBR_ERROR_NONE)
-+ {
-+ ErrorHandler(aResponse, HttpStatusCode::kStatusInternalServerError);
-+ }
-+}
-+
- void Resource::Dataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const
- {
- std::string errorCode;
-
- switch (aRequest.GetMethod())
- {
-+ case HttpMethod::kDelete:
-+ DeleteDataset(aDatasetType, aResponse);
-+ break;
- case HttpMethod::kGet:
- GetDataset(aDatasetType, aRequest, aResponse);
- break;
-diff --git a/src/rest/resource.hpp b/src/rest/resource.hpp
-index d79085dbfc..362e501471 100644
---- a/src/rest/resource.hpp
-+++ b/src/rest/resource.hpp
-@@ -150,6 +150,7 @@ private:
- void GetDataRloc(Response &aResponse) const;
- void GetDataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const;
- void SetDataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const;
-+ void DeleteDataset(DatasetType aDatasetType, Response &aResponse) const;
-
- void DeleteOutDatedDiagnostic(void);
- void UpdateDiag(std::string aKey, std::vector &aDiag);
---
-2.42.0
-
diff --git a/openthread_border_router/0002-spinel-Clear-source-match-tables-before-restoring.patch b/openthread_border_router/0002-spinel-Clear-source-match-tables-before-restoring.patch
new file mode 100644
index 00000000000..f23ae4f73bb
--- /dev/null
+++ b/openthread_border_router/0002-spinel-Clear-source-match-tables-before-restoring.patch
@@ -0,0 +1,32 @@
+From 668b240bddca3e4813e6bb07b438c18f170dac5d Mon Sep 17 00:00:00 2001
+Message-ID: <668b240bddca3e4813e6bb07b438c18f170dac5d.1762891338.git.stefan@agner.ch>
+In-Reply-To: <5d539271f0a5eed0319684d2e8d293d5e37b4aaf.1762891338.git.stefan@agner.ch>
+References: <5d539271f0a5eed0319684d2e8d293d5e37b4aaf.1762891338.git.stefan@agner.ch>
+From: Stefan Agner
+Date: Fri, 7 Nov 2025 18:32:54 +0100
+Subject: [PATCH] [spinel] Clear source match tables before restoring
+
+---
+ src/lib/spinel/radio_spinel.cpp | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp
+index f467c1f28..3e90582aa 100644
+--- a/src/lib/spinel/radio_spinel.cpp
++++ b/src/lib/spinel/radio_spinel.cpp
+@@ -2207,6 +2207,12 @@ void RadioSpinel::RestoreProperties(void)
+ otLinkGetFrameCounter(mInstance) + kFrameCounterGuard));
+ }
+
++ // Clear source match tables before restoring to ensure there's room for entries.
++ // This is especially important when RCP is not fully reset (e.g., in multipan mode)
++ // where stale entries may remain and fill up the limited hardware table.
++ IgnoreError(ClearSrcMatchShortEntries());
++ IgnoreError(ClearSrcMatchExtEntries());
++
+ for (int i = 0; i < mSrcMatchShortEntryCount; ++i)
+ {
+ SuccessOrDie(
+--
+2.51.2
+
diff --git a/openthread_border_router/0003-openthread-set-netif-route-metric-lower.patch b/openthread_border_router/0003-openthread-set-netif-route-metric-lower.patch
deleted file mode 100644
index fcc0504887f..00000000000
--- a/openthread_border_router/0003-openthread-set-netif-route-metric-lower.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From e1857ad3e14df6e950d51cd1f76c12f1c0f59f18 Mon Sep 17 00:00:00 2001
-Message-ID:
-From: Stefan Agner
-Date: Sat, 20 Jan 2024 16:31:28 +0100
-Subject: [PATCH] [openthread] set netif route metric lower
-
-It seems that routes learned through IPv6 Neighbor Discovery Protocol
-get a metric of 128 when NetworkManager is used. Make sure the
-OpenThread network interface's own route is lower than that.
----
- third_party/openthread/CMakeLists.txt | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/third_party/openthread/CMakeLists.txt b/third_party/openthread/CMakeLists.txt
-index f07625da96..0bcca3b79c 100644
---- a/third_party/openthread/CMakeLists.txt
-+++ b/third_party/openthread/CMakeLists.txt
-@@ -105,6 +105,7 @@ target_compile_definitions(ot-config INTERFACE
- "-DOPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS=3"
- "-DOPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE=1"
- "-DOPENTHREAD_CONFIG_TCP_ENABLE=0"
-+ "-DOPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC=64"
- "-DOPENTHREAD_POSIX_CONFIG_FILE=\"${PROJECT_BINARY_DIR}/src/agent/openthread-otbr-posix-config.h\""
- )
-
---
-2.43.0
-
diff --git a/openthread_border_router/CHANGELOG.md b/openthread_border_router/CHANGELOG.md
index 57f7f246c70..22b277cbc00 100644
--- a/openthread_border_router/CHANGELOG.md
+++ b/openthread_border_router/CHANGELOG.md
@@ -1,5 +1,111 @@
# Changelog
+## 2.16.4
+
+- Fix race condition during startup if web frontend is enabled
+
+## 2.16.3
+- Ignore ephemeral temporary settings files in migration
+
+## 2.16.2
+- Fix TREL being disabled by default in beta mode
+
+## 2.16.1
+- Fix listen address of OTBR Web UI
+
+## 2.16.0
+- Add beta toggle to switch between Thread 1.3 (stable) and Thread 1.4 (beta)
+- Beta mode uses OpenThread's built-in mDNS instead of mDNSResponder
+
+## 2.15.3
+- Fix inconsistent startup for adapters that remap hardware flow control pins for firmware flashing.
+
+## 2.15.2
+- Add baudrate list option 1000000 (Nordic Semiconductor nRF Connect SDK firmware)
+
+## 2.15.1
+- Make radio spinel recovery more reliable by clearing source match tables before restoring
+
+## 2.15.0
+- Automatically migrate the active dataset to a new adapter when changing the addon serial port path.
+
+## 2.14.0
+- Remove firmware flashing from the addon, this is now handled by Core 2025.7.0.
+
+## 2.13.0
+- Bump to OTBR POSIX version b067e5ac (2025-01-13 22:32:22 -0500)
+- Bump universal-silabs-flasher to 0.0.28
+- Remove dataset deletion REST API backwards compatibility patch. The minimum Core version for this add-on is now 2023.9.0
+
+## 2.12.4
+
+- Fix OTBR addon does not start after updating containerd.io to 1.7.24-1
+
+## 2.12.3
+
+- Enable recovery mechanism from "radio tx timeout" errors
+- Increase the number of mesh header fragmentation tag entries to address
+ "Failed to get forwarded frame priority" notice messages in logs. Note that
+ these types of messages are non-critical (default priority will be applied in
+ that case).
+- Make some compile time configurations via project header file
+
+## 2.12.2
+
+- Update flasher script to work with Home Assistant Yellow with CM5
+
+## 2.12.1
+- Fix possible race condition between otbr-agent-configure and otbr-agent-rest-discovery
+ services causing failed startup ([#3826](https://github.com/home-assistant/addons/issues/3826))
+
+## 2.12.0
+- Bump universal-silabs-flasher to 0.0.23
+- Bump OTBR firmwares to latest versions
+- Bump to OTBR POSIX version b041fa52daa (2024-11-14 08:18:28 -0800)
+- Add radio firmware version to discovery information
+
+## 2.11.1
+
+- Fix issue with USB TI CC2652 based devices
+
+## 2.11.0
+
+- Bump to OTBR POSIX version ff7227ea9a2 (2024-09-25 14:54:08 -0700)
+- Make log output unbuffered
+- Avoid ipset errors when firewall is disabled
+
+## 2.10.0
+
+- Bump to OTBR POSIX version b66cabfaa0 (2024-08-14 08:01:56 -0700)
+- Avoid OTBR Web spamming system console
+- Bump universal SiLabs flasher to 0.0.22
+
+## 2.9.1
+
+- Abort firmware flasher if network device is selected
+
+## 2.9.0
+
+- Avoid triggering reset/boot loader on TI CC2652 based devices
+
+## 2.8.0
+
+- Bump to OTBR POSIX version 41474ce29a (2024-06-21 08:41:31 -0700)
+
+## 2.7.0
+
+- Support auto firmware updates for Sonoff ZBDongle-E
+- Support auto firmware updates for SMLIGHT SLZB-07
+- Bump universal SiLabs flasher to 0.0.20
+
+## 2.6.0
+
+- Add support for network sockets using socat
+
+## 2.5.1
+
+- Support Home Assistant Connect ZBT-1.
+
## 2.5.0
- Bump to OTBR POSIX version 2279c02f3c (2024-02-28 22:36:55 -0800)
diff --git a/openthread_border_router/DOCS.md b/openthread_border_router/DOCS.md
index 9b7cafc294e..c67b0d75fda 100644
--- a/openthread_border_router/DOCS.md
+++ b/openthread_border_router/DOCS.md
@@ -1,20 +1,25 @@
-# Home Assistant Add-on: OpenThread Border Router
+# Home Assistant App: OpenThread Border Router
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly knowon as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**.
-2. Click on the top right menu and "Repository"
-3. Add "https://github.com/home-assistant/addons" to add the "Home Assistant Add-on Repository for Development" repository.
-4. Find the "OpenThread Border Router" add-on and click it.
-5. Click on the "INSTALL" button.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Select the top right menu and **Repository**.
+3. Add "https://github.com/home-assistant/addons" to add the **Home Assistant App Repository for Development** repository.
+4. Find the **OpenThread Border Router** app and select it.
+5. Select the **Install** button.
## How to use
-You will need a 802.15.4 capable radio supported by OpenThread. Home Assistant
-Yellow as well as Home Assistant SkyConnect are both capable to run OpenThread.
-This add-on automatically installs the necessary firmware on these systems.
+You will need a 802.15.4 capable radio supported by OpenThread flashed with OpenThread
+RCP firmware:
+- Home Assistant Yellow
+- Home Assistant SkyConnect/Connect ZBT-1
+- Home Assistant Connect ZBT-2
+
+These devices are all capable to run OpenThread and will be flashed with the correct
+firmware by Home Assistant Core.
If you are using Home Assistant Yellow, choose `/dev/ttyAMA1` as device.
@@ -29,14 +34,14 @@ RCP firmware for the nRF52840 Dongle.
Once the firmware is loaded follow the following steps:
-1. Select the correct `device` in the add-on configuration tab and press `Save`.
-2. Start the add-on.
+1. Select the correct `device` in the app configuration tab and press `Save`.
+2. Start the app.
### OpenThread Border Router
-This add-on makes your Home Assistant installation an OpenThread Border Router
+This app makes your Home Assistant installation an OpenThread Border Router
(OTBR). The border router can be used to comission Matter devices which connect
-through Thread. Home Assistant Core will automatically detect this add-on and
+through Thread. Home Assistant Core will automatically detect this app and
create a new integration named "Open Thread Border Router". With Home Assistant
Core 2023.3 and newer the OTBR will get configured automatically. The Thread
integration allows to inspect the network configuration.
@@ -45,7 +50,7 @@ integration allows to inspect the network configuration.
There is also a web interface provided by the OTBR. However, the web
interface has caveats (e.g. forming a network does not generate an off-mesh
-routable IPv6 prefix which causes changing IPv6 addressing on first add-on
+routable IPv6 prefix which causes changing IPv6 addressing on first app
restart). It is still possible to enable the web interface for debugging
purpose. Make sure to expose both the Web UI port and REST API port (the
latter needs to be on port 8081) on the host interface. To do so, click on
@@ -54,17 +59,35 @@ and 8081 in the OpenThread REST API port field).
## Configuration
-Add-on configuration:
+App configuration:
| Configuration | Description |
|--------------------|--------------------------------------------------------|
| device (mandatory) | Serial port where the OpenThread RCP Radio is attached |
| baudrate | Serial port baudrate (depends on firmware) |
| flow_control | If hardware flow control should be enabled (depends on firmware) |
-| autoflash_firmware | Automatically install/update firmware (Home Assistant SkyConnect/Yellow) |
| otbr_log_level | Set the log level of the OpenThread BorderRouter Agent |
| firewall | Enable OpenThread Border Router firewall to block unnecessary traffic |
| nat64 | Enable NAT64 to allow Thread devices accessing IPv4 addresses |
+| network_device | IP address and port to connect to a network-based RCP (see below) |
+| beta | Enable beta mode with Thread 1.4 and native OpenThread mDNS |
+
+> [!WARNING]
+> The OTBR expects the RCP connected radio to be on a reliable link such as
+> UART or SPI. Using TCP/IP to reach a remote RCP radio breaks this assumption.
+> If the TCP/IP connection fails, the OTBR will not shutdown cleanly and leave
+> stale routes in your network. This will lead to Thread devices to be
+> potentially unreachable for up to 30 minutes (route lifetime) even when other
+> routers are available.
+>
+> The RCP protocol is not designed to be transferred over an IP network: It is
+> a timing-sensitive protocol. You might experience Thread issues if your
+> network link has excessive latencies. As Thread is networking capable,
+> running a Thread border router on the system the RCP radio is plugged in is
+> recommended.
+
+> [!NOTE]
+> When using a network device, you still need to set a dummy serial port device, e.g. `/dev/ttyS3`.
## Support
@@ -84,5 +107,4 @@ In case you've found a bug, please [open an issue on our GitHub][issue].
[issue]: https://github.com/home-assistant/addons/issues
[openthread-platforms]: https://openthread.io/platforms
[nordic-nrf52840-dongle]: https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle
-[nordic-nrf52840-dongle-install]: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/matter/openthread_rcp_nrf_dongle.html
-
+[nordic-nrf52840-dongle-install]: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/thread/tools.html#configuring_a_radio_co-processor
diff --git a/openthread_border_router/Dockerfile b/openthread_border_router/Dockerfile
index 69f7d257faf..6564f3118ad 100644
--- a/openthread_border_router/Dockerfile
+++ b/openthread_border_router/Dockerfile
@@ -1,70 +1,119 @@
ARG BUILD_FROM
-FROM $BUILD_FROM
-ARG BUILD_ARCH
-ARG OTBR_VERSION
-ARG UNIVERSAL_SILABS_FLASHER
-
-# Set shell
+# OTBR builder stage (beta)
+FROM ${BUILD_FROM} AS otbr-beta-builder
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
-ENV BORDER_ROUTING 1
-ENV BACKBONE_ROUTER 1
-ENV PLATFORM debian
-ENV RELEASE 1
-ENV WEB_GUI 1
-ENV REST_API 1
-ENV DOCKER 1
+ARG OTBR_BETA_VERSION
-COPY 0001-Avoid-writing-to-system-console.patch /usr/src
-COPY 0002-rest-support-deleting-the-dataset.patch /usr/src
-COPY 0003-openthread-set-netif-route-metric-lower.patch /usr/src
-COPY 0001-channel-monitor-disable-by-default.patch /usr/src
+ENV BORDER_ROUTING=1
+ENV BACKBONE_ROUTER=1
+ENV PLATFORM=debian
+ENV RELEASE=1
+ENV WEB_GUI=1
+ENV REST_API=1
+ENV DOCKER=1
-# Required and installed (script/bootstrap) can be removed after build
-ENV OTBR_BUILD_DEPS build-essential ninja-build cmake wget ca-certificates \
- libreadline-dev libncurses-dev libcpputest-dev libdbus-1-dev libavahi-common-dev \
- libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev \
- libnetfilter-queue-dev
-# Installed during build (script/bootstrap) but unused in our configuration
-ENV OTBR_UNUSED_DEBS libavahi-client3 avahi-daemon rsyslog
+COPY openthread-core-ha-config-posix.h /usr/src/
WORKDIR /usr/src
+RUN \
+ set -x \
+ && apt-get update \
+ # The OTBR build script tries to run `sudo`
+ && apt-get install -y --no-install-recommends sudo git \
+ && git clone --depth 1 -b main https://github.com/openthread/ot-br-posix.git /usr/src/ot-br-posix \
+ && cd /usr/src/ot-br-posix \
+ && git fetch origin ${OTBR_BETA_VERSION} \
+ && git checkout ${OTBR_BETA_VERSION} \
+ && git submodule update --init \
+ # Bootstrap downloads a few more repos
+ && ./script/bootstrap \
+ # Remove libsystemd-dev to avoid unnecessary linkage
+ && apt-get purge -y libsystemd-dev
+
+WORKDIR /usr/src/ot-br-posix
+RUN \
+ set -x \
+ && mv /usr/src/openthread-core-ha-config-posix.h /usr/src/ot-br-posix/third_party/openthread/repo/ \
+ && ./script/cmake-build \
+ -DBUILD_TESTING=OFF \
+ -DCMAKE_INSTALL_PREFIX=/opt/otbr-beta \
+ -DOTBR_FEATURE_FLAGS=ON \
+ -DOTBR_MDNS=openthread \
+ -DOTBR_VERSION= \
+ -DOT_PACKAGE_VERSION= \
+ -DOTBR_DBUS=OFF \
+ -DOT_POSIX_RCP_HDLC_BUS=ON \
+ -DOTBR_VENDOR_NAME="Home Assistant" \
+ -DOTBR_PRODUCT_NAME="OpenThread Border Router" \
+ # The Meshcop service name is specified in `openthread-core-ha-config-posix.h`
+ -DOTBR_WEB=ON \
+ -DOTBR_BORDER_ROUTING=ON \
+ -DOTBR_REST=ON \
+ -DOTBR_BACKBONE_ROUTER=ON \
+ -DOTBR_TREL=ON \
+ -DOTBR_NAT64=ON \
+ -DOT_POSIX_NAT64_CIDR="192.168.255.0/24" \
+ -DOTBR_DNS_UPSTREAM_QUERY=ON \
+ -DOT_CHANNEL_MONITOR=ON \
+ -DOT_COAP=OFF \
+ -DOT_COAPS=OFF \
+ -DOT_THREAD_VERSION=1.4 \
+ -DOT_PROJECT_CONFIG="/usr/src/ot-br-posix/third_party/openthread/repo/openthread-core-ha-config-posix.h" \
+ && cd /usr/src/ot-br-posix/build/otbr \
+ && ninja install
+
+
+# OTBR builder stage (stable)
+FROM ${BUILD_FROM} AS otbr-stable-builder
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+ARG OTBR_VERSION
+
+ENV BORDER_ROUTING=1
+ENV BACKBONE_ROUTER=1
+ENV PLATFORM=debian
+ENV RELEASE=1
+ENV WEB_GUI=1
+ENV REST_API=1
+ENV DHCPV6_PD_REF=0
+ENV DOCKER=1
-# Install npm/nodejs for WebUI before calling script/bootstrap to avoid
-# systemd getting pulled in
+
+COPY openthread-core-ha-config-posix.h /usr/src/
+COPY 0001-channel-monitor-disable-by-default.patch /usr/src/
+COPY 0002-spinel-Clear-source-match-tables-before-restoring.patch /usr/src/
+
+WORKDIR /usr/src
RUN \
set -x \
&& apt-get update \
- && apt-get install -y --no-install-recommends \
- iproute2 \
- python3 \
- python3-pip \
- lsb-release \
- netcat-openbsd \
- sudo \
- git \
- nodejs \
- npm \
- && git clone --depth 1 -b main \
- https://github.com/openthread/ot-br-posix.git \
- && cd ot-br-posix \
+ # The OTBR build script tries to run `sudo`
+ && apt-get install -y --no-install-recommends sudo git \
+ && git clone --depth 1 -b main https://github.com/openthread/ot-br-posix.git /usr/src/ot-br-posix \
+ && cd /usr/src/ot-br-posix \
&& git fetch origin ${OTBR_VERSION} \
&& git checkout ${OTBR_VERSION} \
&& git submodule update --init \
+ # Bootstrap downloads a few more repos
&& ./script/bootstrap \
- && patch -p1 < /usr/src/0001-Avoid-writing-to-system-console.patch \
- && patch -p1 < /usr/src/0002-rest-support-deleting-the-dataset.patch \
- && patch -p1 < /usr/src/0003-openthread-set-netif-route-metric-lower.patch \
- && (cd third_party/openthread/repo && \
- patch -p1 < /usr/src/0001-channel-monitor-disable-by-default.patch) \
- # Mimic rt_tables_install \
- && echo "88 openthread" >> /etc/iproute2/rt_tables \
- # Mimic otbr_install \
- && (./script/cmake-build \
+ # Remove libsystemd-dev to avoid unnecessary linkage
+ && apt-get purge -y libsystemd-dev
+
+WORKDIR /usr/src/ot-br-posix
+RUN \
+ set -x \
+ && mv /usr/src/openthread-core-ha-config-posix.h /usr/src/ot-br-posix/third_party/openthread/repo/ \
+ && ( \
+ cd third_party/openthread/repo \
+ && patch -p1 < /usr/src/0001-channel-monitor-disable-by-default.patch \
+ && patch -p1 < /usr/src/0002-spinel-Clear-source-match-tables-before-restoring.patch \
+ ) \
+ && ./script/cmake-build \
-DBUILD_TESTING=OFF \
- -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_INSTALL_PREFIX=/opt/otbr-stable \
-DOTBR_FEATURE_FLAGS=ON \
-DOTBR_DNSSD_DISCOVERY_PROXY=ON \
-DOTBR_SRP_ADVERTISING_PROXY=ON \
@@ -87,21 +136,54 @@ RUN \
-DOT_CHANNEL_MONITOR=ON \
-DOT_COAP=OFF \
-DOT_COAPS=OFF \
- && cd build/otbr/ \
- && ninja \
- && ninja install) \
- && pip install --break-system-packages \
- universal-silabs-flasher==${UNIVERSAL_SILABS_FLASHER} \
- && apt-get purge -y --auto-remove \
- git \
- nodejs \
- npm \
- ${OTBR_BUILD_DEPS} \
- ${OTBR_UNUSED_DEBS} \
- && rm -rf /var/lib/apt/lists/* \
- && rm -rf /usr/src/*
+ -DOT_DNS_CLIENT_OVER_TCP=OFF \
+ -DOT_THREAD_VERSION=1.3 \
+ -DOT_PROJECT_CONFIG="/usr/src/ot-br-posix/third_party/openthread/repo/openthread-core-ha-config-posix.h" \
+ -DOT_RCP_RESTORATION_MAX_COUNT=2 \
+ && cd /usr/src/ot-br-posix/build/otbr \
+ && ninja install
+
+# Runtime image
+FROM ${BUILD_FROM}
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+ARG SERIALX_VERSION
+ARG UNIVERSAL_SILABS_FLASHER_VERSION
+
+# Install runtime dependencies
+RUN \
+ set -x \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ python3 \
+ python3-pip \
+ netcat-openbsd \
+ socat \
+ iproute2 \
+ iputils-ping \
+ ipset \
+ iptables \
+ libreadline8 \
+ libncurses6 \
+ libprotobuf-lite32 \
+ libjsoncpp26 \
+ && pip install --break-system-packages --no-cache-dir \
+ universal-silabs-flasher==${UNIVERSAL_SILABS_FLASHER_VERSION} \
+ serialx==${SERIALX_VERSION} \
+ && rm -rf /var/lib/apt/lists/*
+
+# Setup routing table for OpenThread
+RUN \
+ mkdir -p /etc/iproute2 \
+ && echo "88 openthread" >> /etc/iproute2/rt_tables
+
+COPY --from=otbr-beta-builder /opt/otbr-beta /opt/otbr-beta
+COPY --from=otbr-stable-builder /opt/otbr-stable /opt/otbr-stable
+COPY --from=otbr-stable-builder /usr/sbin/mdnsd /opt/otbr-stable/sbin/mdnsd
+COPY --from=otbr-stable-builder /usr/lib/libdns_sd.so /usr/lib/libdns_sd.so
+COPY --from=otbr-stable-builder /usr/lib/libdns_sd.so.1 /usr/lib/libdns_sd.so.1
COPY rootfs /
ENV \
- S6_STAGE2_HOOK=/etc/s6-overlay/scripts/otbr-web-enable-check.sh
+ S6_STAGE2_HOOK=/etc/s6-overlay/scripts/enable-check.sh
diff --git a/openthread_border_router/README.md b/openthread_border_router/README.md
index d8493cdb13c..3fb1076dad3 100644
--- a/openthread_border_router/README.md
+++ b/openthread_border_router/README.md
@@ -1,10 +1,10 @@
-# Home Assistant Add-on: OpenThread Border Router Add-on
+# Home Assistant App: OpenThread Border Router App
-OpenThread Border Router add-on. The add-on uses the upstream OpenThread
-Border Router implementation and wraps it as an add-on for Home Assistant.
+OpenThread Border Router app (formerly known as add-on). The app uses the upstream OpenThread
+Border Router implementation and wraps it as an app for Home Assistant.
**NOTE:** This requires a supported 802.15.4 capable radio with OpenThread
-RCP firmware. If you are using Home Assistant Yellow or SkyConnect then
+RCP firmware. If you are using [Home Assistant Yellow](https://www.home-assistant.io/yellow/) or [Home Assistant Connect ZBT-1](https://www.home-assistant.io/connectzbt1/) (previously called SkyConnect) then
the correct firmware is automatically installed.
![Supports aarch64 Architecture][aarch64-shield]
@@ -12,7 +12,7 @@ the correct firmware is automatically installed.
## About
-This add-on allows you to form or join a Thread network and make Home Assistant
+This app allows you to form or join a Thread network and make Home Assistant
a Thread Border Router.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/openthread_border_router/build.yaml b/openthread_border_router/build.yaml
index 826013bef34..fbd59ff7031 100644
--- a/openthread_border_router/build.yaml
+++ b/openthread_border_router/build.yaml
@@ -1,7 +1,9 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
- amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:trixie
+ amd64: ghcr.io/home-assistant/amd64-base-debian:trixie
args:
- OTBR_VERSION: 2279c02f3c3373f074899fc8d993b8ddb72910a2
- UNIVERSAL_SILABS_FLASHER: 0.0.18
+ OTBR_BETA_VERSION: 624a7d98e0dac5984c2982068f71fc81d2dbceb5
+ OTBR_VERSION: b067e5ac5f8b3e92750df24922017eee2bc0fa04
+ UNIVERSAL_SILABS_FLASHER_VERSION: 0.1.2
+ SERIALX_VERSION: 0.5.0
diff --git a/openthread_border_router/config.yaml b/openthread_border_router/config.yaml
index a95da12ba74..e61b100d5f1 100644
--- a/openthread_border_router/config.yaml
+++ b/openthread_border_router/config.yaml
@@ -1,5 +1,5 @@
---
-version: 2.5.0
+version: 2.16.4
slug: openthread_border_router
name: OpenThread Border Router
description: OpenThread Border Router add-on
@@ -8,7 +8,7 @@ url: >-
arch:
- aarch64
- amd64
-homeassistant: 2023.6.0.dev20230531
+homeassistant: 2025.7.0
gpio: true
hassio_api: true
discovery:
@@ -20,16 +20,18 @@ host_uts: true
privileged:
- IPC_LOCK
- NET_ADMIN
+devices:
+ - /dev/net/tun
image: homeassistant/{arch}-addon-otbr
init: false
options:
device: null
baudrate: "460800"
flow_control: true
- autoflash_firmware: true
otbr_log_level: notice
firewall: true
nat64: false
+ beta: false
ports:
8080/tcp: null
8081/tcp: null
@@ -38,10 +40,11 @@ ports_description:
8081/tcp: OpenThread REST API port
schema:
device: device(subsystem=tty)
- baudrate: list(57600|115200|230400|460800|921600)
+ baudrate: list(57600|115200|230400|460800|921600|1000000)
flow_control: bool
- autoflash_firmware: bool
+ network_device: str?
otbr_log_level: list(debug|info|notice|warning|error|critical|alert|emergency)
firewall: bool
nat64: bool
+ beta: bool?
startup: services
diff --git a/openthread_border_router/logo.png b/openthread_border_router/logo.png
index 63b2611bc9f..c80bce24065 100644
Binary files a/openthread_border_router/logo.png and b/openthread_border_router/logo.png differ
diff --git a/openthread_border_router/openthread-core-ha-config-posix.h b/openthread_border_router/openthread-core-ha-config-posix.h
new file mode 100644
index 00000000000..7dd33cc070d
--- /dev/null
+++ b/openthread_border_router/openthread-core-ha-config-posix.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OPENTHREAD_CORE_HA_CONFIG_POSIX_H_
+#define OPENTHREAD_CORE_HA_CONFIG_POSIX_H_
+
+/**
+ * This header file defines the OpenThread core configuration options for
+ * Home Assistant with POSIX platform.
+ */
+
+/**
+ * It seems that routes learned through IPv6 Neighbor Discovery Protocol
+ * get a metric of 128 when NetworkManager is used. Make sure the
+ * OpenThread network interface's own route is lower than that, to ensure
+ * that the local radio is preferred over learned routes.
+ */
+#define OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC 64
+
+/**
+ * Increase delay aware queue management entry list size from its default of
+ * 16 to 64. This is to avoid/decrease the number of "Failed to get forwarded
+ * frame priority" notice messages.
+ */
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE 64
+
+/**
+ * The impact on production systems is not entirly clear. The channel scan could lead to
+ * missed packets. Disabling by default allows to enable the feature at compile time so
+ * developers and users can enable it at runtime for testing.
+ */
+#define OPENTHREAD_CONFIG_CHANNEL_MONITOR_AUTO_START_ENABLE 0
+
+/**
+ * @def OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME
+ *
+ * Specifies the base name to construct the service instance name used when advertising the mDNS `_meshcop._udp`
+ * service by the Border Agent.
+ *
+ * Applicable when the `OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE` feature is enabled.
+ *
+ * The name can also be configured using the `otBorderAgentSetMeshCoPServiceBaseName()` API at run-time.
+ *
+ * Per the Thread specification, the service instance should be a user-friendly name identifying the device model or
+ * product. A recommended format is "VendorName ProductName".
+ *
+ * The name MUST have a length less than or equal to `OT_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME_MAX_LENGTH` (47 chars).
+ */
+#define OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME "Home Assistant OpenThread Border Router "
+
+#endif /* OPENTHREAD_CORE_HA_CONFIG_POSIX_H_ */
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
index 208999d7977..92b89c6b491 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# mDNSResponder finish script
#==============================================================================
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
index 4d80c10f1da..bcbcb033f3b 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
@@ -1,10 +1,12 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start mDNSResponder daemon
# ==============================================================================
bashio::log.info "Starting mDNS Responder..."
# mdnsd runs as daemon except when using debug mode. We prefer non-daemon, so
-# start in debug by default. It seems nto to generate a vast amount of
+# start in debug by default. It seems not to generate a vast amount of
# messages.
exec /usr/sbin/mdnsd -debug
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent-configure
similarity index 100%
rename from openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner
rename to openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent-configure
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check
index 662155dbcd4..8722f197b88 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check
@@ -1,6 +1,9 @@
#!/bin/bash
+set -e
# Check if openthread socket exists
+test -S /run/openthread-wpan0.sock
+
+# Check REST API port is open
mapfile -t < /tmp/otbr-agent-rest-api
-test -S /run/openthread-wpan0.sock && nc -z "${MAPFILE[@]}"
-exit
+nc -z "${MAPFILE[@]}"
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
index dede3e34b9c..7ece6a29d75 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# OpenThread BorderRouter Daemon finish script
#==============================================================================
@@ -14,6 +16,7 @@ else
bashio::log.info "otbr-agent exited with code $e (by signal $2)."
fi
+# shellcheck disable=SC1091
. /etc/s6-overlay/scripts/otbr-agent-common
ipset_destroy_if_exist()
@@ -25,10 +28,13 @@ ipset_destroy_if_exist()
done
}
+# shellcheck disable=SC2154,SC2086
while ip6tables -C FORWARD -o $thread_if -j $otbr_forward_ingress_chain 2> /dev/null; do
+ # shellcheck disable=SC2086
ip6tables -D FORWARD -o $thread_if -j $otbr_forward_ingress_chain
done
+# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_ingress_chain 2> /dev/null; then
ip6tables -w -F $otbr_forward_ingress_chain
ip6tables -w -X $otbr_forward_ingress_chain
@@ -39,10 +45,12 @@ ipset_destroy_if_exist otbr-ingress-deny-src-swap
ipset_destroy_if_exist otbr-ingress-allow-dst
ipset_destroy_if_exist otbr-ingress-allow-dst-swap
+# shellcheck disable=SC2154,SC2086
while ip6tables -C FORWARD -i $thread_if -j $otbr_forward_egress_chain 2> /dev/null; do
ip6tables -D FORWARD -i $thread_if -j $otbr_forward_egress_chain
done
+# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_egress_chain 2> /dev/null; then
ip6tables -w -F $otbr_forward_egress_chain
ip6tables -w -X $otbr_forward_egress_chain
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
index 41dea6a24f4..94dcbcccc44 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
@@ -1,26 +1,44 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# OpenThread BorderRouter start script
# ==============================================================================
+# shellcheck disable=SC1091
. /etc/s6-overlay/scripts/otbr-agent-common
declare backbone_if
declare device
declare baudrate
declare flow_control
+declare migrate_flow_control
declare otbr_log_level
declare otbr_log_level_int
declare otbr_rest_listen
declare otbr_rest_listen_port
+# Cleanup unused configs
+if bashio::config.exists 'autoflash_firmware'; then
+ bashio::addon.option 'autoflash_firmware'
+fi
+
backbone_if="$(bashio::api.supervisor 'GET' '/network/info' '' 'first(.interfaces[] | select (.primary == true)) .interface')"
device=$(bashio::config 'device')
+
+if bashio::config.has_value 'network_device'; then
+ device="/tmp/ttyOTBR"
+fi
+
baudrate=$(bashio::config 'baudrate')
flow_control=""
if bashio::config.true 'flow_control'; then
flow_control="&uart-flow-control"
+ migrate_flow_control="hardware"
+else
+ flow_control="&uart-init-deassert"
+ migrate_flow_control="none"
fi
otbr_log_level=$(bashio::string.lower "$(bashio::config otbr_log_level)")
@@ -54,31 +72,46 @@ case "${otbr_log_level}" in
;;
esac
+# shellcheck disable=SC2086
if [ -z ${backbone_if} ]; then
bashio::log.warning "No primary network interface found! Using static eth0."
backbone_if="eth0"
fi
+# shellcheck disable=SC2015
mkdir -p /data/thread && ln -sft /var/lib /data/thread || bashio::exit.nok "Could not create directory /var/lib/thread to store Thread data."
+# We compile the OTBR with firewall support, so otbr-agent tries to update the
+# ipsets. Therefor, create ipsets always to avoid errors from otbr-agent. Just
+# the ipsets won't have an effect in practice when the firewall is disabled.
+ipset create -exist otbr-ingress-deny-src hash:net family inet6
+ipset create -exist otbr-ingress-deny-src-swap hash:net family inet6
+ipset create -exist otbr-ingress-allow-dst hash:net family inet6
+ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6
+
if bashio::config.true 'firewall'; then
bashio::log.info "Setup OTBR firewall..."
- ipset create -exist otbr-ingress-deny-src hash:net family inet6
- ipset create -exist otbr-ingress-deny-src-swap hash:net family inet6
- ipset create -exist otbr-ingress-allow-dst hash:net family inet6
- ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6
-
+# shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_ingress_chain
+# shellcheck disable=SC2086,SC2154
ip6tables -I FORWARD 1 -o $thread_if -j $otbr_forward_ingress_chain
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -i ${thread_if} -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-deny-src src -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -j ACCEPT
+ # shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_egress_chain
+ # shellcheck disable=SC2086
ip6tables -I FORWARD 2 -i $thread_if -j $otbr_forward_egress_chain
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_egress_chain -j ACCEPT
else
# Make sure ip6tables (as used by Docker) allow IP forwarding
@@ -88,9 +121,12 @@ else
fi
if bashio::config.true 'nat64'; then
+ # shellcheck disable=SC2086
iptables -t mangle -A PREROUTING -i ${thread_if} -j MARK --set-mark 0x1001
iptables -t nat -A POSTROUTING -m mark --mark 0x1001 -j MASQUERADE
+ # shellcheck disable=SC2086
iptables -t filter -A FORWARD -o ${backbone_if} -j ACCEPT
+ # shellcheck disable=SC2086
iptables -t filter -A FORWARD -i ${backbone_if} -j ACCEPT
fi
@@ -110,10 +146,19 @@ fi
echo "${otbr_rest_listen}" > /tmp/otbr-agent-rest-api
echo "${otbr_rest_listen_port}" >> /tmp/otbr-agent-rest-api
+# Migrate OTBR settings to new adapter if needed
+bashio::log.info "Migrating OTBR settings if needed..."
+python3 /usr/local/bin/migrate_otbr_settings.py \
+ --adapter "${device}" \
+ --baudrate "${baudrate}" \
+ --flow-control "${migrate_flow_control}" \
+ --data-dir /data/thread/
+
bashio::log.info "Starting otbr-agent..."
-exec s6-notifyoncheck -d -s 300 -w 300 -n 0 \
+# shellcheck disable=SC2086
+exec s6-notifyoncheck -d -s 300 -w 300 -n 0 stdbuf -oL \
"/usr/sbin/otbr-agent" -I ${thread_if} -B "${backbone_if}" \
--rest-listen-address "${otbr_rest_listen}" \
- -d${otbr_log_level_int} -v \
+ -d${otbr_log_level_int} -v -s \
"spinel+hdlc+uart://${device}?uart-baudrate=${baudrate}${flow_control}" \
"trel://${backbone_if}"
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent-configure
similarity index 100%
rename from openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns
rename to openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent-configure
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
index 2c9cd489043..2035d588936 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# OpenThread BorderRouter web interface finish script
#==============================================================================
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
index 53fc7e616a0..427f025404d 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start OpenThread BorderRouter web interface
# ==============================================================================
@@ -7,4 +9,4 @@ declare otbr_web_port
otbr_web_port="$(bashio::addon.port 8080)"
-exec /usr/sbin/otbr-web -I wpan0 -d6 -p "${otbr_web_port}"
+exec stdbuf -oL /usr/sbin/otbr-web -I wpan0 -d6 -s -a "::" -p "${otbr_web_port}"
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check
new file mode 100755
index 00000000000..b41abdafe79
--- /dev/null
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+test -c /tmp/ttyOTBR
+exit
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/notification-fd b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/notification-fd
similarity index 100%
rename from openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/notification-fd
rename to openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/notification-fd
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run
new file mode 100755
index 00000000000..c81a9ef86f2
--- /dev/null
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run
@@ -0,0 +1,15 @@
+#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# Start socat TCP client for OTBR agent daemon
+# ==============================================================================
+
+declare network_device
+
+network_device=$(bashio::config 'network_device')
+
+bashio::log.info "Starting socat TCP client for OTBR daemon..."
+exec s6-notifyoncheck -d -s 300 -w 300 \
+ "/usr/bin/socat" -d pty,raw,echo=0,link=/tmp/ttyOTBR,ignoreeof \
+ "tcp:${network_device}"
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type
new file mode 100644
index 00000000000..5883cff0cd1
--- /dev/null
+++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type
@@ -0,0 +1 @@
+longrun
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type
deleted file mode 100644
index bdd22a1850a..00000000000
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type
+++ /dev/null
@@ -1 +0,0 @@
-oneshot
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up
deleted file mode 100644
index 56e09fe7678..00000000000
--- a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up
+++ /dev/null
@@ -1 +0,0 @@
-/etc/s6-overlay/scripts/universal-silabs-flasher-up
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh
index 37a8218fdf5..074dc4179e5 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh
+++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: Base Images
# Displays a simple add-on banner on startup
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh
new file mode 100755
index 00000000000..96b730d5a2d
--- /dev/null
+++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Select OTBR version and enable mDNSResponder for stable mode
+# ==============================================================================
+
+if bashio::config.true 'beta'; then
+ bashio::log.info "Beta mode enabled, using OpenThread built-in mDNS."
+
+ ln -sf "/opt/otbr-beta/sbin/otbr-agent" /usr/sbin/otbr-agent
+ ln -sf "/opt/otbr-beta/sbin/otbr-web" /usr/sbin/otbr-web
+ ln -sf "/opt/otbr-beta/sbin/ot-ctl" /usr/sbin/ot-ctl
+else
+ bashio::log.info "Stable mode, enabling mDNSResponder."
+
+ touch /etc/s6-overlay/s6-rc.d/user/contents.d/mdns
+ touch /etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/mdns
+
+ ln -sf "/opt/otbr-stable/sbin/otbr-agent" /usr/sbin/otbr-agent
+ ln -sf "/opt/otbr-stable/sbin/otbr-web" /usr/sbin/otbr-web
+ ln -sf "/opt/otbr-stable/sbin/ot-ctl" /usr/sbin/ot-ctl
+ ln -sf "/opt/otbr-stable/sbin/mdnsd" /usr/sbin/mdnsd
+fi
+
+# ==============================================================================
+# Disable OTBR Web if necessary ports are not exposed
+# ==============================================================================
+
+if bashio::var.has_value "$(bashio::addon.port 8080)" \
+ && bashio::var.has_value "$(bashio::addon.port 8081)"; then
+ bashio::log.info "Web UI and REST API port are exposed, starting otbr-web."
+else
+ rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web
+ bashio::log.info "The otbr-web is disabled."
+fi
+
+# ==============================================================================
+# Enable socat-otbr-tcp service if needed
+# ==============================================================================
+
+if bashio::config.has_value 'network_device'; then
+ touch /etc/s6-overlay/s6-rc.d/user/contents.d/socat-otbr-tcp
+ touch /etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/socat-otbr-tcp
+ bashio::log.info "Enabled socat-otbr-tcp."
+fi
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh
index 348c835e940..8a4cc94e635 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh
+++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh
@@ -1,8 +1,11 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Configure OTBR depending on add-on settings
# ==============================================================================
+ot-ctl trel enable
+
if bashio::config.true 'nat64'; then
bashio::log.info "Enabling NAT64."
ot-ctl nat64 enable
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
index 7377f674867..190bfd7dd45 100755
--- a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
+++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Send OTBR discovery information to Home Assistant
# ==============================================================================
@@ -7,6 +8,8 @@ declare config
config=$(bashio::var.json \
host "$(bashio::addon.hostname)" \
port "^8081" \
+ device "$(bashio::config 'device')" \
+ firmware "$(ot-ctl rcp version | head -n 1)" \
)
# Send discovery info
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-web-enable-check.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-web-enable-check.sh
deleted file mode 100755
index 8bd256fd9f1..00000000000
--- a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-web-enable-check.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# ==============================================================================
-# Disable OTBR Web if necessary ports are not exposed
-# ==============================================================================
-
-if bashio::var.has_value "$(bashio::addon.port 8080)" \
- && bashio::var.has_value "$(bashio::addon.port 8081)"; then
- bashio::log.info "Web UI and REST API port are exposed, starting otbr-web."
-else
- rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web
- bashio::log.info "The otbr-web is disabled."
-fi
diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
deleted file mode 100755
index 23b8c422d6f..00000000000
--- a/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# ==============================================================================
-# Start universal-silabs-flasher if requested
-# ==============================================================================
-
-declare autoflash_firmware
-declare device
-declare firmware
-declare usb_device_path
-declare usb_manufacturer
-declare usb_product
-declare gpio_reset_flag
-
-function exit_no_firmware {
- bashio::log.warning "No firmware found for the selected device, assuming firmware is installed."
- exit 0
-}
-
-device=$(bashio::config 'device')
-
-if bashio::config.false 'autoflash_firmware'; then
- bashio::log.info "Flashing firmware is disabled"
- exit 0
-fi
-
-# Assume to run on Yellow if UART4 is mapped to ttyAMA1
-if [ -d /sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1 ] && [ "${device}" == "/dev/ttyAMA1" ]; then
- bashio::log.info "Detected Home Assistant Yellow"
- firmware="NabuCasa_Yellow_OpenThread_RCP_v2.4.0.0_PA32_ot-rcp_hw_460800.gbl"
- gpio_reset_flag="--yellow-gpio-reset"
-else
- # Check device manufacturer/product information
- usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}))/../../../../)
- if [ ! -f "${usb_device_path}/idProduct" ]; then
- bashio::log.info "The selected serial port is not a USB device."
- exit_no_firmware
- fi
-
- if [ ! -f "${usb_device_path}/manufacturer" ] || [ ! -f "${usb_device_path}/product" ]; then
- bashio::log.info "USB device is missing manufacturer or product name."
- exit_no_firmware
- fi
-
- usb_manufacturer=$(cat "${usb_device_path}/manufacturer")
- usb_product=$(cat "${usb_device_path}/product")
-
- bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}."
- if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then
- firmware="NabuCasa_SkyConnect_OpenThread_RCP_v2.4.0.0_ot-rcp_hw_460800.gbl"
- else
- exit_no_firmware
- fi
- gpio_reset_flag=""
-fi
-
-bashio::log.info "Starting universal-silabs-flasher with ${device}"
-exec universal-silabs-flasher --device ${device} \
- flash ${gpio_reset_flag} --ensure-exact-version --allow-cross-flashing --firmware "/root/${firmware}"
diff --git a/openthread_border_router/rootfs/root/NabuCasa_SkyConnect_OpenThread_RCP_v2.4.0.0_ot-rcp_hw_460800.gbl b/openthread_border_router/rootfs/root/NabuCasa_SkyConnect_OpenThread_RCP_v2.4.0.0_ot-rcp_hw_460800.gbl
deleted file mode 100644
index efc4b32e912..00000000000
Binary files a/openthread_border_router/rootfs/root/NabuCasa_SkyConnect_OpenThread_RCP_v2.4.0.0_ot-rcp_hw_460800.gbl and /dev/null differ
diff --git a/openthread_border_router/rootfs/root/NabuCasa_Yellow_OpenThread_RCP_v2.4.0.0_PA32_ot-rcp_hw_460800.gbl b/openthread_border_router/rootfs/root/NabuCasa_Yellow_OpenThread_RCP_v2.4.0.0_PA32_ot-rcp_hw_460800.gbl
deleted file mode 100644
index a2940520ef6..00000000000
Binary files a/openthread_border_router/rootfs/root/NabuCasa_Yellow_OpenThread_RCP_v2.4.0.0_PA32_ot-rcp_hw_460800.gbl and /dev/null differ
diff --git a/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py b/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py
new file mode 100755
index 00000000000..c31043ce03e
--- /dev/null
+++ b/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py
@@ -0,0 +1,228 @@
+import asyncio
+import argparse
+import datetime
+import re
+import zigpy.serial
+from pathlib import Path
+from serialx import PinState
+
+from enum import Enum
+from universal_silabs_flasher.spinel import (
+ SpinelProtocol,
+ CommandID,
+ PropertyID,
+ ResetReason,
+)
+
+CONNECT_TIMEOUT = 10
+AFTER_DISCONNECT_DELAY = 1
+SETTINGS_FILE_PATTERN = re.compile(r"^\d+_[0-9a-f]+\.data$")
+
+
+class OtbrSettingsKey(Enum):
+ ACTIVE_DATASET = 0x0001
+ PENDING_DATASET = 0x0002
+ NETWORK_INFO = 0x0003
+ PARENT_INFO = 0x0004
+ CHILD_INFO = 0x0005
+ SLAAC_IID_SECRET_KEY = 0x0007
+ DAD_INFO = 0x0008
+ SRP_ECDSA_KEY = 0x000B
+ SRP_CLIENT_INFO = 0x000C
+ SRP_SERVER_INFO = 0x000D
+ BR_ULA_PREFIX = 0x000F
+ BR_ON_LINK_PREFIXES = 0x0010
+ BORDER_AGENT_ID = 0x0011
+
+
+def parse_otbr_settings(data: bytes) -> list[tuple[OtbrSettingsKey, bytes]]:
+ """Parses an OTBR binary settings file."""
+ settings = []
+
+ while data:
+ key_bytes = data[:2]
+ if not key_bytes:
+ break
+
+ assert len(key_bytes) == 2
+ key = int.from_bytes(key_bytes, "little")
+
+ length_bytes = data[2:4]
+ assert len(length_bytes) == 2
+
+ length = int.from_bytes(length_bytes, "little")
+ value = data[4 : 4 + length]
+ assert len(value) == length
+
+ settings.append((OtbrSettingsKey(key), value))
+ data = data[4 + length :]
+
+ return settings
+
+
+def serialize_otbr_settings(settings: list[tuple[OtbrSettingsKey, bytes]]) -> bytes:
+ """Serialize OTBR binary settings."""
+ data = b""
+
+ for key, value in settings:
+ key_bytes = key.value.to_bytes(2, "little")
+ length_bytes = len(value).to_bytes(2, "little")
+ data += key_bytes + length_bytes + value
+
+ return data
+
+
+def is_valid_otbr_settings_file(settings: list[tuple[OtbrSettingsKey, bytes]]) -> bool:
+ """Check if parsed settings represent a valid OTBR settings file."""
+ return {OtbrSettingsKey.ACTIVE_DATASET} <= {key for key, _ in settings}
+
+
+async def get_adapter_hardware_addr(
+ port: str, baudrate: int = 460800, flow_control: str | None = None
+) -> str:
+ loop = asyncio.get_running_loop()
+
+ async with asyncio.timeout(CONNECT_TIMEOUT):
+ _, protocol = await zigpy.serial.create_serial_connection(
+ loop=loop,
+ protocol_factory=SpinelProtocol,
+ url=port,
+ baudrate=baudrate,
+ flow_control=flow_control,
+ # OTBR uses `uart-init-deassert` when flow control is disabled
+ rtsdtr_on_open=(
+ PinState.HIGH if flow_control == "hardware" else PinState.LOW
+ ),
+ rtsdtr_on_close=PinState.LOW,
+ )
+ await protocol.wait_until_connected()
+
+ await protocol.reset(ResetReason.STACK)
+
+ try:
+ rsp = await protocol.send_command(
+ CommandID.PROP_VALUE_GET,
+ PropertyID.HWADDR.serialize(),
+ )
+ finally:
+ await protocol.disconnect()
+
+ prop_id, hwaddr = PropertyID.deserialize(rsp.data)
+ assert prop_id == PropertyID.HWADDR
+
+ return hwaddr.hex()
+
+
+def hwaddr_to_filename(hwaddr: str) -> str:
+ port_offset = 0
+ node_id = int(hwaddr, 16)
+
+ return f"{port_offset}_{node_id:x}.data"
+
+
+def backup_file(path: Path) -> Path:
+ suffix = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
+ backup_path = path.with_suffix(path.suffix + f".backup-{suffix}")
+ path.rename(backup_path)
+ return backup_path
+
+
+async def main() -> None:
+ parser = argparse.ArgumentParser(description="Migrate OTBR settings to new adapter")
+ parser.add_argument(
+ "--data-dir", type=Path, help="Path to OTBR data directory", required=True
+ )
+ parser.add_argument(
+ "--adapter", type=str, help="Serial port of the new adapter", required=True
+ )
+ parser.add_argument(
+ "--baudrate", type=int, default=460800, help="Baudrate of the new adapter"
+ )
+ parser.add_argument(
+ "--flow-control",
+ type=str,
+ default="none",
+ help="Flow control for the serial connection (hardware, software, or none)",
+ )
+
+ args = parser.parse_args()
+
+ flow_control = args.flow_control
+
+ if flow_control == "none":
+ flow_control = None
+
+ # First, read the hardware address of the new adapter
+ hwaddr = await get_adapter_hardware_addr(
+ port=args.adapter,
+ baudrate=args.baudrate,
+ flow_control=flow_control,
+ )
+
+ # Then, look at existing settings
+ all_settings = []
+
+ for settings_path in args.data_dir.glob("*.data"):
+ if not SETTINGS_FILE_PATTERN.match(settings_path.name):
+ continue
+
+ mod_time = settings_path.stat().st_mtime
+ otbr_settings = parse_otbr_settings(settings_path.read_bytes())
+
+ # Ensure our parsing is valid
+ assert serialize_otbr_settings(otbr_settings) == settings_path.read_bytes()
+
+ if not is_valid_otbr_settings_file(otbr_settings):
+ print(
+ f"Settings file {settings_path} is not a valid OTBR settings file, skipping"
+ )
+ continue
+
+ all_settings.append((mod_time, settings_path, otbr_settings))
+
+ if not all_settings:
+ print("No existing settings files found, skipping")
+ return
+
+ most_recent_settings_info = sorted(all_settings, reverse=True)[0]
+ most_recent_settings_path = most_recent_settings_info[1]
+ most_recent_settings = most_recent_settings_info[2]
+
+ expected_settings_path = args.data_dir / hwaddr_to_filename(hwaddr)
+
+ if expected_settings_path.exists():
+ if most_recent_settings_path == expected_settings_path:
+ print(
+ f"Adapter settings file {expected_settings_path} is the most recently used, skipping"
+ )
+ return
+
+ # If the settings file is old, we should "delete" it
+ print(
+ f"Settings file for adapter {hwaddr} already exists at {expected_settings_path} but appears to be old, archiving"
+ )
+ backup_file(expected_settings_path)
+
+ # Write back a new settings file that keeps only a few keys
+ new_settings = [
+ (key, value)
+ for key, value in most_recent_settings
+ if key
+ in (
+ OtbrSettingsKey.ACTIVE_DATASET,
+ OtbrSettingsKey.PENDING_DATASET,
+ OtbrSettingsKey.CHILD_INFO,
+ )
+ ]
+
+ expected_settings_path.write_bytes(serialize_otbr_settings(new_settings))
+ print(f"Wrote new settings file to {expected_settings_path}")
+
+ await asyncio.sleep(AFTER_DISCONNECT_DELAY)
+
+
+if __name__ == "__main__":
+ import coloredlogs
+
+ coloredlogs.install(level="DEBUG")
+ asyncio.run(main())
diff --git a/openthread_border_router/translations/en.yaml b/openthread_border_router/translations/en.yaml
index 77c912fc842..7dd371bf4e2 100644
--- a/openthread_border_router/translations/en.yaml
+++ b/openthread_border_router/translations/en.yaml
@@ -10,11 +10,12 @@ configuration:
flow_control:
name: Hardware flow control
description: Enable hardware flow control for serial port.
- autoflash_firmware:
- name: Automatically flash firmware
+ network_device:
+ name: Network Device
description: >-
- Automatically flash OpenThread RCP firmware on Home Assistant Yellow and
- SkyConnect.
+ when connecting to a device via sockets (takes precedence
+ over above configuration). Not recommended! See documentation for more
+ information.
otbr_log_level:
name: OpenThread Border Router agent log level
description: >-
@@ -28,6 +29,10 @@ configuration:
description: >-
Enable IPv6 to IPv4 network address translation. This allows Thread
devices to communicate with devices on the Internet.
+ beta:
+ name: Beta
+ description: >-
+ Enable beta mode with Thread 1.4 and native OpenThread mDNS.
network:
8080/tcp: OpenThread Web port
8081/tcp: OpenThread REST API port
diff --git a/openwakeword/CHANGELOG.md b/openwakeword/CHANGELOG.md
index 7f4f96145ea..7f5f8d79cf8 100644
--- a/openwakeword/CHANGELOG.md
+++ b/openwakeword/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## 2.1.0
+
+- Upgrade to wyoming-openwakeword 2.1.0
+- Fix zeroconf discovery
+- Drop support for `armv7`
+
## 1.10.0
- Upgrade to wyoming 1.5.3
diff --git a/openwakeword/DOCS.md b/openwakeword/DOCS.md
index 63b21436a67..8fee800ff2b 100644
--- a/openwakeword/DOCS.md
+++ b/openwakeword/DOCS.md
@@ -1,16 +1,16 @@
-# Home Assistant Add-on: openWakeWord
+# Home Assistant App: openWakeWord
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "openWakeWord" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "openWakeWord" app and click it.
3. Click on the "INSTALL" button.
## How to use
-After this add-on is installed and running, it will be automatically discovered
+After this app is installed and running, it will be automatically discovered
by the Wyoming integration in Home Assistant. To finish the setup,
click the following my button:
@@ -38,7 +38,7 @@ Enable debug logging. Useful for seeing satellite connections and each wake word
## Custom Wake Word Models
-The add-on will automatically load custom wake word models from the `/share/openwakeword` directory. [Install the Samba add-on](https://www.home-assistant.io/common-tasks/supervised/#installing-and-using-the-samba-add-on) to copy wake word model files (`*.tflite`) to this directory.
+The app will automatically load custom wake word models from the `/share/openwakeword` directory. [Install the Samba app](https://www.home-assistant.io/common-tasks/supervised/#installing-and-using-the-samba-app) to copy wake word model files (`*.tflite`) to this directory.
After adding new models to `/share/openwakeword`, make sure to reload any Wyoming integrations for openWakeWord. Once reloaded, the new wake words will be available to select in the Voice Assistants settings page.
diff --git a/openwakeword/Dockerfile b/openwakeword/Dockerfile
index c4c3858b89b..da233bb5823 100644
--- a/openwakeword/Dockerfile
+++ b/openwakeword/Dockerfile
@@ -15,13 +15,13 @@ RUN \
netcat-traditional \
python3 \
python3-pip \
- libopenblas0 \
\
&& pip3 install --no-cache-dir -U \
setuptools \
wheel \
&& pip3 install --no-cache-dir \
--extra-index-url https://www.piwheels.org/simple \
+ "wyoming[zeroconf]>=1.8,<2" \
"wyoming-openwakeword @ https://github.com/rhasspy/wyoming-openwakeword/archive/refs/tags/v${WYOMING_OPENWAKEWORD_VERSION}.tar.gz" \
\
&& rm -rf /var/lib/apt/lists/*
diff --git a/openwakeword/README.md b/openwakeword/README.md
index 4496fd41817..ba53554a888 100644
--- a/openwakeword/README.md
+++ b/openwakeword/README.md
@@ -1,8 +1,8 @@
-# Home Assistant Add-on: openWakeWord
+# Home Assistant App: openWakeWord
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armv7 Architecture][armv7-shield]
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
-Home Assistant add-on that uses [openWakeWord](https://github.com/dscripka/openwakeword) for wake word detection.
+Home Assistant app (formerly known as add-on) that uses [pyopen-wakeword](https://github.com/rhasspy/pyopen-wakeword) for wake word detection.
Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/).
@@ -10,6 +10,3 @@ Requires Home Assistant 2023.9 or later.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg
-[i386-shield]: https://img.shields.io/badge/i386-no-red.svg
diff --git a/openwakeword/build.yaml b/openwakeword/build.yaml
index e880a2dd014..d6a946d9721 100644
--- a/openwakeword/build.yaml
+++ b/openwakeword/build.yaml
@@ -2,9 +2,5 @@
build_from:
amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
- armv7: ghcr.io/home-assistant/armv7-base-debian:bookworm
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
args:
- WYOMING_OPENWAKEWORD_VERSION: 1.10.0
+ WYOMING_OPENWAKEWORD_VERSION: 2.1.0
diff --git a/openwakeword/config.yaml b/openwakeword/config.yaml
index cb2254ef922..d5d5ed782ec 100644
--- a/openwakeword/config.yaml
+++ b/openwakeword/config.yaml
@@ -1,5 +1,5 @@
---
-version: 1.10.0
+version: 2.1.0
slug: openwakeword
name: openWakeWord
description: openWakeWord using the Wyoming protocol
@@ -7,7 +7,6 @@ url: https://github.com/home-assistant/addons/blob/master/openwakeword
arch:
- amd64
- aarch64
- - armv7
init: false
discovery:
- wyoming
diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
index e217ccda1be..b584069e104 100755
--- a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
+++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Sends discovery information to Home Assistant.
diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish
index 2911a30fa93..8558b9a95ea 100755
--- a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish
+++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish
@@ -1,10 +1,11 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run
index 6e77aa8fcef..7db54150326 100755
--- a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run
+++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start openWakeWord service
@@ -9,9 +10,10 @@ if bashio::config.true 'debug_logging'; then
flags+=('--debug')
fi
+# shellcheck disable=SC2068
exec python3 -m wyoming_openwakeword \
--uri 'tcp://0.0.0.0:10400' \
- --preload-model 'ok_nabu' \
+ --zeroconf \
--custom-model-dir /share/openwakeword \
--threshold "$(bashio::config 'threshold')" \
--trigger-level "$(bashio::config 'trigger_level')" ${flags[@]}
diff --git a/piper/CHANGELOG.md b/piper/CHANGELOG.md
index 52842b23908..f764c735403 100644
--- a/piper/CHANGELOG.md
+++ b/piper/CHANGELOG.md
@@ -1,5 +1,59 @@
# Changelog
+## 2.2.2
+
+- Upgrade to `wyoming-piper` 2.2.2 (wheel fix)
+
+## 2.2.1
+
+- Upgrade to `wyoming-piper` 2.2.1
+- Add support for new Chinese voices
+
+## 2.1.1
+
+- Upgrade to `wyoming-piper` 2.1.1
+- Streaming is enabled by default (remove `streaming` option)
+- Remove `max_piper_procs` option (no longer applicable)
+- Drop support for `armv7`
+- Fix zeroconf discovery
+
+## 1.6.4
+
+- Add missing voice for Argentinian Spanish (daniela)
+
+## 1.6.3
+
+- Bump wyoming to 1.7.2 to fix event data error
+
+## 1.6.2
+
+- Split sentences on numbered lists and remove asterisks surrounding words
+- Remove asterisks at the start of a line (markdown list)
+- Add new voices for Malayalam (arjun, meera)
+- Add new voice for Nepali (chitwan)
+- Add new voices for Hindi (pratham, priyamvada)
+- Add new voice for Argentinian Spanish (daniela)
+
+## 1.6.0
+
+- Add support for streaming audio on sentence boundaries
+
+## 1.5.4
+
+- Add voices for Dutch: ronnie, pim
+- Add voice for English: sam
+- Add voice for Persian/English: reza_ibrahim
+- Add voice for Persian: ganji
+- Add voices for Portuguese (Brazilian): cadu, jeff
+
+## 1.5.2
+
+- Add missing voices supported by Piper (gwryw_gogleddol, bryce, john, norman and paola)
+
+## 1.5.1
+
+- Add voice for English: cori
+
## 1.5.0
- Add voices for Persian: amir, gyro
diff --git a/piper/DOCS.md b/piper/DOCS.md
index 7ffa39ed134..a6c80289d01 100644
--- a/piper/DOCS.md
+++ b/piper/DOCS.md
@@ -1,16 +1,16 @@
-# Home Assistant Add-on: Piper
+# Home Assistant App: Piper
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Piper" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Piper" app and click it.
3. Click on the "INSTALL" button.
## How to use
-After this add-on is installed and running, it will be automatically discovered
+After this app is installed and running, it will be automatically discovered
by the Wyoming integration in Home Assistant. To finish the setup,
click the following my button:
@@ -59,23 +59,13 @@ Controls the variability of audio by adding noise during audio generation. The e
Controls the variability of speaking cadence (phoneme widths). The effect highly depends on the voice itself, but in general a value of 0 removes variability and values above 1 produce extreme stutters and pauses.
-### Option: `max_piper_procs`
-
-Number of Piper processes to run simultaneously (default is 1). Each Piper process loads a single voice model into RAM, so using multiple voices at the same time requires:
-
-- Starting/stopping Piper processes as voices are used, or
-- Running more Piper processes
-
-This add-on will start a Piper process for each requested voice up to `max_piper_procs`. After that, the least recently used voice will be stopped.
-Increase `max_piper_procs` if you need to quickly switch between multiple voices, but beware that this will increase RAM usage by the add-on.
-
### Option: `update_voices`
-Download the list of new voices automatically every time the add-on starts. You must also reload the Wyoming integration for Piper in Home Assistant to see new voices.
+Download the list of new voices automatically every time the app starts. You must also reload the Wyoming integration for Piper in Home Assistant to see new voices.
### Option: `debug_logging`
-Print DEBUG level messages to the add-on's log.
+Print DEBUG level messages to the app's log.
## Custom Voices
diff --git a/piper/Dockerfile b/piper/Dockerfile
index 8969f0b8c32..4bc932b1204 100644
--- a/piper/Dockerfile
+++ b/piper/Dockerfile
@@ -8,7 +8,6 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
WORKDIR /usr/src
ARG BUILD_ARCH
ARG WYOMING_PIPER_VERSION
-ARG BINARY_PIPER_VERSION
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN \
apt-get update \
@@ -21,13 +20,9 @@ RUN \
setuptools \
wheel \
&& pip3 install --no-cache-dir \
- "wyoming-piper @ https://github.com/rhasspy/wyoming-piper/archive/refs/tags/v${WYOMING_PIPER_VERSION}.tar.gz" \
- \
- && ARCH="${BUILD_ARCH}" \
- && if [[ "${BUILD_ARCH}" = "aarch64" ]]; then ARCH="arm64"; fi \
- && curl -L -s \
- "https://github.com/rhasspy/piper/releases/download/v${BINARY_PIPER_VERSION}/piper_${ARCH}.tar.gz" \
- | tar -zxvf - -C /usr/share \
+ --extra-index-url https://www.piwheels.org/simple \
+ --extra-index-url https://download.pytorch.org/whl/cpu \
+ "wyoming-piper[zeroconf,zh] @ https://github.com/rhasspy/wyoming-piper/archive/refs/tags/v${WYOMING_PIPER_VERSION}.tar.gz" \
\
&& rm -rf /var/lib/apt/lists/*
diff --git a/piper/README.md b/piper/README.md
index 8bd711a1c4e..d0730873c89 100644
--- a/piper/README.md
+++ b/piper/README.md
@@ -1,8 +1,8 @@
-# Home Assistant Add-on: Piper
+# Home Assistant App: Piper
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
-Home Assistant add-on that uses [piper](https://github.com/rhasspy/piper/) for text-to-speech.
+Home Assistant app (formerly known as add-on) that uses [piper](https://github.com/OHF-Voice/piper1-gpl) for text-to-speech.
Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/).
diff --git a/piper/build.yaml b/piper/build.yaml
index be1e3763e5d..6f95b7aef86 100644
--- a/piper/build.yaml
+++ b/piper/build.yaml
@@ -2,9 +2,5 @@
build_from:
amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
args:
- WYOMING_PIPER_VERSION: 1.5.0
- BINARY_PIPER_VERSION: 1.2.0
+ WYOMING_PIPER_VERSION: 2.2.2
diff --git a/piper/config.yaml b/piper/config.yaml
index 9094b6c5a49..6608437d099 100644
--- a/piper/config.yaml
+++ b/piper/config.yaml
@@ -1,5 +1,5 @@
---
-version: 1.5.0
+version: 2.2.2
slug: piper
name: Piper
description: Text-to-speech with Piper
@@ -20,17 +20,15 @@ options:
length_scale: 1.0
noise_scale: 0.667
noise_w: 0.333
- max_piper_procs: 1
debug_logging: false
update_voices: true
schema:
voice: |
- list(ar_JO-kareem-low|ar_JO-kareem-medium|ca_ES-upc_ona-medium|ca_ES-upc_ona-x_low|ca_ES-upc_pau-x_low|cs_CZ-jirka-low|cs_CZ-jirka-medium|da_DK-talesyntese-medium|de_DE-eva_k-x_low|de_DE-karlsson-low|de_DE-kerstin-low|de_DE-mls-medium|de_DE-pavoque-low|de_DE-ramona-low|de_DE-thorsten_emotional-medium|de_DE-thorsten-high|de_DE-thorsten-low|de_DE-thorsten-medium|el_GR-rapunzelina-low|en_GB-alan-low|en_GB-alan-medium|en_GB-alba-medium|en_GB-aru-medium|en_GB-jenny_dioco-medium|en_GB-northern_english_male-medium|en_GB-semaine-medium|en_GB-southern_english_female-low|en_GB-vctk-medium|en_US-amy-low|en_US-amy-medium|en_US-arctic-medium|en_US-danny-low|en_US-hfc_female-medium|en_US-hfc_male-medium|en_US-joe-medium|en_US-kathleen-low|en_US-kusal-medium|en_US-l2arctic-medium|en_US-lessac-high|en_US-lessac-low|en_US-lessac-medium|en_US-libritts-high|en_US-libritts_r-medium|en_US-ryan-high|en_US-ryan-low|en_US-ryan-medium|es_ES-carlfm-x_low|es_ES-davefx-medium|es_ES-mls_10246-low|es_ES-mls_9972-low|es_ES-sharvard-medium|es_MX-ald-medium|fa_IR-amir-medium|fa_IR-gyro-medium|fi_FI-harri-low|fi_FI-harri-medium|fr_FR-gilles-low|fr_FR-mls_1840-low|fr_FR-mls-medium|fr_FR-siwis-low|fr_FR-siwis-medium|fr_FR-tom-medium|fr_FR-upmc-medium|hu_HU-anna-medium|hu_HU-berta-medium|hu_HU-imre-medium|is_IS-bui-medium|is_IS-salka-medium|is_IS-steinn-medium|is_IS-ugla-medium|it_IT-riccardo-x_low|ka_GE-natia-medium|kk_KZ-iseke-x_low|kk_KZ-issai-high|kk_KZ-raya-x_low|lb_LU-marylux-medium|ne_NP-google-medium|ne_NP-google-x_low|nl_BE-nathalie-medium|nl_BE-nathalie-x_low|nl_BE-rdh-medium|nl_BE-rdh-x_low|nl_NL-mls_5809-low|nl_NL-mls_7432-low|nl_NL-mls-medium|no_NO-talesyntese-medium|pl_PL-darkman-medium|pl_PL-gosia-medium|pl_PL-mc_speech-medium|pl_PL-mls_6892-low|pt_BR-edresson-low|pt_BR-faber-medium|pt_PT-tugão-medium|ro_RO-mihai-medium|ru_RU-denis-medium|ru_RU-dmitri-medium|ru_RU-irina-medium|ru_RU-ruslan-medium|sk_SK-lili-medium|sl_SI-artur-medium|sr_RS-serbski_institut-medium|sv_SE-nst-medium|sw_CD-lanfrica-medium|tr_TR-dfki-medium|tr_TR-fahrettin-medium|tr_TR-fettah-medium|uk_UA-lada-x_low|uk_UA-ukrainian_tts-medium|vi_VN-25hours_single-low|vi_VN-vais1000-medium|vi_VN-vivos-x_low|zh_CN-huayan-medium|zh_CN-huayan-x_low|ca-upc_ona-x-low|ca-upc_pau-x-low|da-nst_talesyntese-medium|de-eva_k-x-low|de-karlsson-low|de-kerstin-low|de-pavoque-low|de-ramona-low|de-thorsten-low|el-gr-rapunzelina-low|en-gb-alan-low|en-gb-southern_english_female-low|en-us-amy-low|en-us-danny-low|en-us-kathleen-low|en-us-lessac-low|en-us-lessac-medium|en-us-libritts-high|en-us-ryan-high|en-us-ryan-low|en-us-ryan-medium|es-carlfm-x-low|es-mls_10246-low|es-mls_9972-low|fi-harri-low|fr-gilles-low|fr-mls_1840-low|fr-siwis-low|fr-siwis-medium|is-bui-medium|is-salka-medium|is-steinn-medium|is-ugla-medium|it-riccardo_fasol-x-low|kk-iseke-x-low|kk-issai-high|kk-raya-x-low|ne-google-medium|ne-google-x-low|nl-mls_5809-low|nl-mls_7432-low|nl-nathalie-x-low|nl-rdh-medium|nl-rdh-x-low|no-talesyntese-medium|pl-mls_6892-low|pt-br-edresson-low|ru-irinia-medium|uk-lada-x-low|vi-25hours-single-low|vi-vivos-x-low|zh-cn-huayan-x-low)
+ list(ar_JO-kareem-low|ar_JO-kareem-medium|ca_ES-upc_ona-medium|ca_ES-upc_ona-x_low|ca_ES-upc_pau-x_low|ca-upc_ona-x-low|ca-upc_pau-x-low|cs_CZ-jirka-low|cs_CZ-jirka-medium|cy_GB-bu_tts-medium|cy_GB-gwryw_gogleddol-medium|da_DK-talesyntese-medium|da-nst_talesyntese-medium|de_DE-eva_k-x_low|de_DE-karlsson-low|de_DE-kerstin-low|de_DE-mls-medium|de_DE-pavoque-low|de_DE-ramona-low|de_DE-thorsten_emotional-medium|de_DE-thorsten-high|de_DE-thorsten-low|de_DE-thorsten-medium|de-eva_k-x-low|de-karlsson-low|de-kerstin-low|de-pavoque-low|de-ramona-low|de-thorsten-low|el-gr-rapunzelina-low|el_GR-rapunzelina-low|en-gb-alan-low|en_GB-alan-low|en_GB-alan-medium|en_GB-alba-medium|en_GB-aru-medium|en_GB-cori-high|en_GB-cori-medium|en_GB-jenny_dioco-medium|en_GB-northern_english_male-medium|en_GB-semaine-medium|en-gb-southern_english_female-low|en_GB-southern_english_female-low|en_GB-vctk-medium|en-us-amy-low|en_US-amy-low|en_US-amy-medium|en_US-arctic-medium|en_US-bryce-medium|en-us-danny-low|en_US-danny-low|en_US-hfc_female-medium|en_US-hfc_male-medium|en_US-joe-medium|en_US-john-medium|en-us-kathleen-low|en_US-kathleen-low|en_US-kristin-medium|en_US-kusal-medium|en_US-l2arctic-medium|en_US-lessac-high|en-us-lessac-low|en_US-lessac-low|en-us-lessac-medium|en_US-lessac-medium|en-us-libritts-high|en_US-libritts-high|en_US-libritts_r-medium|en_US-ljspeech-high|en_US-ljspeech-medium|en_US-norman-medium|en_US-reza_ibrahim-medium|en-us-ryan-high|en_US-ryan-high|en-us-ryan-low|en_US-ryan-low|en-us-ryan-medium|en_US-ryan-medium|en_US-sam-medium|es-carlfm-x-low|es_AR-daniela-high|es_ES-carlfm-x_low|es_ES-davefx-medium|es_ES-mls_10246-low|es_ES-mls_9972-low|es_ES-sharvard-medium|es-mls_10246-low|es-mls_9972-low|es_MX-ald-medium|es_MX-claude-high|fa_IR-amir-medium|fa_IR-ganji_adabi-medium|fa_IR-ganji-medium|fa_IR-gyro-medium|fa_IR-reza_ibrahim-medium|fi_FI-harri-low|fi_FI-harri-medium|fi-harri-low|fr_FR-gilles-low|fr_FR-mls_1840-low|fr_FR-mls-medium|fr_FR-siwis-low|fr_FR-siwis-medium|fr_FR-tom-medium|fr_FR-upmc-medium|fr-gilles-low|fr-mls_1840-low|fr-siwis-low|fr-siwis-medium|hi_IN-pratham-medium|hi_IN-priyamvada-medium|hu_HU-anna-medium|hu_HU-berta-medium|hu_HU-imre-medium|is-bui-medium|is_IS-bui-medium|is_IS-salka-medium|is_IS-steinn-medium|is_IS-ugla-medium|is-salka-medium|is-steinn-medium|is-ugla-medium|it_IT-paola-medium|it_IT-riccardo-x_low|it-riccardo_fasol-x-low|ka_GE-natia-medium|kk-iseke-x-low|kk-issai-high|kk_KZ-iseke-x_low|kk_KZ-issai-high|kk_KZ-raya-x_low|kk-raya-x-low|lb_LU-marylux-medium|lv_LV-aivars-medium|ml_IN-arjun-medium|ml_IN-meera-medium|ne-google-medium|ne-google-x-low|ne_NP-chitwan-medium|ne_NP-google-medium|ne_NP-google-x_low|nl_BE-nathalie-medium|nl_BE-nathalie-x_low|nl_BE-rdh-medium|nl_BE-rdh-x_low|nl-mls_5809-low|nl-mls_7432-low|nl-nathalie-x-low|nl_NL-mls_5809-low|nl_NL-mls_7432-low|nl_NL-mls-medium|nl_NL-pim-medium|nl_NL-ronnie-medium|nl-rdh-medium|nl-rdh-x-low|no_NO-talesyntese-medium|no-talesyntese-medium|pl-mls_6892-low|pl_PL-darkman-medium|pl_PL-gosia-medium|pl_PL-mc_speech-medium|pl_PL-mls_6892-low|pt_BR-cadu-medium|pt-br-edresson-low|pt_BR-edresson-low|pt_BR-faber-medium|pt_BR-jeff-medium|pt_PT-tugão-medium|ro_RO-mihai-medium|ru-irinia-medium|ru_RU-denis-medium|ru_RU-dmitri-medium|ru_RU-irina-medium|ru_RU-ruslan-medium|sk_SK-lili-medium|sl_SI-artur-medium|sr_RS-serbski_institut-medium|sv_SE-lisa-medium|sv_SE-nst-medium|sw_CD-lanfrica-medium|tr_TR-dfki-medium|tr_TR-fahrettin-medium|tr_TR-fettah-medium|uk-lada-x-low|uk_UA-lada-x_low|uk_UA-ukrainian_tts-medium|vi-25hours-single-low|vi-vivos-x-low|vi_VN-25hours_single-low|vi_VN-vais1000-medium|vi_VN-vivos-x_low|zh_CN-chaowen-medium|zh_CN-huayan-medium|zh-cn-huayan-x-low|zh_CN-huayan-x_low|zh_CN-xiao_ya-medium)
speaker: int
length_scale: float
noise_scale: float
noise_w: float
- max_piper_procs: int
debug_logging: bool
update_voices: bool
ports:
diff --git a/piper/icon.png b/piper/icon.png
index 098ce412a90..350c9419e0a 100644
Binary files a/piper/icon.png and b/piper/icon.png differ
diff --git a/piper/logo.png b/piper/logo.png
index 2b276be25ab..f75f435c99f 100644
Binary files a/piper/logo.png and b/piper/logo.png differ
diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
index 5d7c4fdac78..17bf8e4c181 100755
--- a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
+++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Sends discovery information to Home Assistant.
diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish
index 2911a30fa93..8558b9a95ea 100755
--- a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish
+++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish
@@ -1,10 +1,11 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run
index e638c7d1ddb..5e6b7b277cd 100755
--- a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run
+++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start Piper service
@@ -12,15 +13,24 @@ if bashio::config.true 'debug_logging'; then
flags+=('--debug')
fi
+# Delete old options
+options=$(bashio::addon.options)
+for old_key in 'max_piper_procs' 'streaming'; do
+ if bashio::jq.exists "${options}" ".${old_key}"; then
+ bashio::log.info "Removing ${old_key}"
+ bashio::addon.option "${old_key}"
+ fi
+done
+
+# shellcheck disable=SC2068
exec python3 -m wyoming_piper \
- --piper '/usr/share/piper/piper' \
--uri 'tcp://0.0.0.0:10200' \
+ --zeroconf \
--length-scale "$(bashio::config 'length_scale')" \
--noise-scale "$(bashio::config 'noise_scale')" \
--noise-w "$(bashio::config 'noise_w')" \
--speaker "$(bashio::config 'speaker')" \
--voice "$(bashio::config 'voice')" \
- --max-piper-procs "$(bashio::config 'max_piper_procs')" \
--data-dir /data \
--data-dir /share/piper \
--download-dir /data ${flags[@]}
diff --git a/piper/translations/en.yaml b/piper/translations/en.yaml
index df874ab7482..3a511acdb91 100644
--- a/piper/translations/en.yaml
+++ b/piper/translations/en.yaml
@@ -27,21 +27,15 @@ configuration:
Controls the variability of speaking cadence (phoneme widths). The effect
highly depends on the voice itself, but in general a value of 0 removes
variability and values above 1 produce extreme stutters and pauses.
- max_piper_procs:
- name: Maximum Piper processes
- description: >-
- Number of Piper processes to run simultaneously (default is 1). Increase
- if you need to quickly switch between multiple voices, but beware that
- this will increase RAM usage by the add-on.
update_voices:
name: Update voices
description: >-
- Download the list of new voices automatically every time the add-on
+ Download the list of new voices automatically every time the app
starts. You must also reload the Wyoming integration for Piper in Home
Assistant to see new voices.
debug_logging:
name: Debug logging
description: >-
- Print DEBUG level messages to the add-on's log.
+ Print DEBUG level messages to the app's log.
network:
10200/tcp: Piper Wyoming Protocol
diff --git a/rpc_shutdown/CHANGELOG.md b/rpc_shutdown/CHANGELOG.md
index 86ebd6b40c3..a38139102fc 100644
--- a/rpc_shutdown/CHANGELOG.md
+++ b/rpc_shutdown/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## 2.5
+
+- Update to Alpine 3.19
+
## 2.4
- Update to Alpine 3.17
diff --git a/rpc_shutdown/DOCS.md b/rpc_shutdown/DOCS.md
index 0f69024ea7a..b8eaa196444 100644
--- a/rpc_shutdown/DOCS.md
+++ b/rpc_shutdown/DOCS.md
@@ -1,23 +1,23 @@
-# Home Assistant Add-on: RPC Shutdown
+# Home Assistant App: RPC Shutdown
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "RPC Shutdown" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "RPC Shutdown" app and click it.
3. Click on the "INSTALL" button.
## How to use
In the configuration section, define alias, address and credentials and save the configuration.
-1. Start the add-on.
-2. Check the add-on log output to see the result.
+1. Start the app.
+2. Check the app log output to see the result.
## Configuration
-Add-on configuration:
+App configuration:
```yaml
computers:
@@ -60,20 +60,20 @@ Show a custom message on the screen of the computer that will be shutdown.
## Home Assistant configuration
-Use the following inside Home Assistant service call to use it:
+Use the following inside Home Assistant action call to use it:
```yaml
-service: hassio.addon_stdin
+action: hassio.app_stdin
data:
- addon: core_rpc_shutdown
+ app: core_rpc_shutdown
input: test-pc
```
Each line explained:
-`service: hassio.addon_stdin`: Use hassio.addon_stdin service to send data over STDIN to an add-on.
-`data.addon: core_rpc_shutdown`: Tells the service to send the command to this add-on.
-`data.input: test-pc`: Alias name created for the computer in the add-on configuration, and shuts that one down.
+`action: hassio.app_stdin`: Use hassio.app_stdin service to send data over STDIN to an app.
+`data.app: core_rpc_shutdown`: Tells the service to send the command to this app.
+`data.input: test-pc`: Alias name created for the computer in the app configuration, and shuts that one down.
## Support
diff --git a/rpc_shutdown/README.md b/rpc_shutdown/README.md
index 92992fa3926..1497ce3b1dc 100644
--- a/rpc_shutdown/README.md
+++ b/rpc_shutdown/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: RPC Shutdown
+# Home Assistant App: RPC Shutdown
Shutdown Windows machines remotely.
diff --git a/rpc_shutdown/build.yaml b/rpc_shutdown/build.yaml
index 896c0b943d2..19306375de0 100644
--- a/rpc_shutdown/build.yaml
+++ b/rpc_shutdown/build.yaml
@@ -1,10 +1,7 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.17
- amd64: ghcr.io/home-assistant/amd64-base:3.17
- armhf: ghcr.io/home-assistant/armhf-base:3.17
- armv7: ghcr.io/home-assistant/armv7-base:3.17
- i386: ghcr.io/home-assistant/i386-base:3.17
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.19
+ amd64: ghcr.io/home-assistant/amd64-base:3.19
+ armhf: ghcr.io/home-assistant/armhf-base:3.19
+ armv7: ghcr.io/home-assistant/armv7-base:3.19
+ i386: ghcr.io/home-assistant/i386-base:3.19
diff --git a/rpc_shutdown/config.yaml b/rpc_shutdown/config.yaml
index 472ea466e1d..58cb902e23d 100644
--- a/rpc_shutdown/config.yaml
+++ b/rpc_shutdown/config.yaml
@@ -1,5 +1,5 @@
---
-version: "2.4"
+version: "2.5"
slug: rpc_shutdown
name: RPC Shutdown
description: Shutdown Windows machines remotely
diff --git a/rpc_shutdown/data/run.sh b/rpc_shutdown/data/run.sh
index 6dd8139e4da..f3d5e2cec61 100755
--- a/rpc_shutdown/data/run.sh
+++ b/rpc_shutdown/data/run.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
set -e
# Read from STDIN aliases to send shutdown
diff --git a/samba/CHANGELOG.md b/samba/CHANGELOG.md
index baf686bedfd..0f9bd4a2171 100644
--- a/samba/CHANGELOG.md
+++ b/samba/CHANGELOG.md
@@ -1,5 +1,37 @@
# Changelog
+## 12.5.4
+
+- Fix invalid inverted commas in server signing parameter
+
+## 12.5.3
+
+- Add option for setting server signing parameter
+
+## 12.5.2
+
+- Avoid binding to disabled network interfaces
+
+## 12.5.1
+
+- Add configurations option to disable Apple devices interoperability. Disabling this setting might be required for file systems that do not support extended attributes such as exFAT.
+
+## 12.5.0
+
+- Add the ability to enable and disable trying to become a local master browser on a subnet
+
+## 12.4.0
+
+- Add the ability to enable and disable specific shares, improving user control over folder access
+
+## 12.3.3
+
+- Enable Samba configurations to improve interoperability with Apple devices
+
+## 12.3.2
+
+- Suppress benign idmap logged error
+
## 12.3.1
- Handle passwords with backslash correctly
diff --git a/samba/DOCS.md b/samba/DOCS.md
index 2e6408198e1..0ed6bfffc26 100644
--- a/samba/DOCS.md
+++ b/samba/DOCS.md
@@ -1,45 +1,52 @@
-# Home Assistant Add-on: Samba share
+# Home Assistant App: Samba share
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Samba share" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Samba share" app and click it.
3. Click on the "INSTALL" button.
## How to use
1. In the configuration section, set a username and password.
You can specify any username and password; these are not related in any way to the login credentials you use to log in to Home Assistant or to log in to the computer with which you will use Samba share.
-2. Save the configuration.
-3. Start the add-on.
-4. Check the add-on log output to see the result.
+2. Review the enabled shares. Disable any you do not plan to use. Shares can be re-enabled later if needed.
## Connection
If you are on Windows you use `\\\`, if you are on MacOS you use `smb://` to connect to the shares.
-This addon exposes the following directories over smb (samba):
+This app exposes the following directories over smb (samba):
Directory | Description
-- | --
-`addons` | This is for your local add-ons.
-`addon_configs` | This is for the configuration files of your add-ons.
+`addons` | This is for your local apps.
+`addon_configs` | This is for the configuration files of your apps.
`backup` | This is for your backups.
`config` | This is for your Home Assistant configuration.
`media` | This is for local media files.
-`share` | This is for your data that is shared between add-ons and Home Assistant.
+`share` | This is for your data that is shared between apps and Home Assistant.
`ssl` | This is for your SSL certificates.
## Configuration
-Add-on configuration:
+App configuration:
```yaml
workgroup: WORKGROUP
+local_master: true
username: homeassistant
password: YOUR_PASSWORD
+enabled_shares:
+ - addons
+ - addon_configs
+ - backup
+ - config
+ - media
+ - share
+ - ssl
allow_hosts:
- 10.0.0.0/8
- 172.16.0.0/12
@@ -58,6 +65,10 @@ compatibility_mode: false
Change WORKGROUP to reflect your network needs.
+### Option: `local_master` (required)
+
+Enable to try and become a local master browser on a subnet.
+
### Option: `username` (required)
The username you would like to use to authenticate with the Samba server.
@@ -66,6 +77,10 @@ The username you would like to use to authenticate with the Samba server.
The password that goes with the username configured for authentication.
+### Option: `enabled_shares` (required)
+
+List of Samba shares that will be accessible. Any shares removed or commented out of the list will not be accessible.
+
### Option: `allow_hosts` (required)
List of hosts/networks allowed to access the shared folders.
@@ -79,12 +94,26 @@ from littering the share with temporary hidden files
### Option: `compatibility_mode`
Setting this option to `true` will enable old legacy Samba protocols
-on the Samba add-on. This might solve issues with some clients that cannot
+on the Samba app. This might solve issues with some clients that cannot
handle the newer protocols, however, it lowers security. Only use this
when you absolutely need it and understand the possible consequences.
Defaults to `false`.
+### Option: `apple_compatibility_mode`
+
+Enable Samba configurations to improve interoperability with Apple devices.
+This can cause issues with file systems that do not support xattr such as exFAT.
+
+Defaults to `true`.
+
+### Option: `server_signing`
+
+Configure the SMB server signing requirement. This option can improve security by requiring message signing, which helps prevent man-in-the-middle attacks.
+Refer to the man page for smb.conf for detailed information about the values: **default**, **auto**, **mandatory**, and **disabled**.
+
+Defaults to `default`.
+
## Support
Got questions?
diff --git a/samba/README.md b/samba/README.md
index d9b07ba46de..3b5d7a117fb 100644
--- a/samba/README.md
+++ b/samba/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: Samba share
+# Home Assistant App: Samba share
Share your configuration over the network using Windows file sharing.
@@ -6,7 +6,7 @@ Share your configuration over the network using Windows file sharing.
## About
-This Add-on allows you to enable file sharing across different operating systems over a network.
+This app (formerly known as add-on) allows you to enable file sharing across different operating systems over a network.
It lets you access your config files with Windows and macOS devices.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/samba/build.yaml b/samba/build.yaml
index 039821f92e6..19306375de0 100644
--- a/samba/build.yaml
+++ b/samba/build.yaml
@@ -5,6 +5,3 @@ build_from:
armhf: ghcr.io/home-assistant/armhf-base:3.19
armv7: ghcr.io/home-assistant/armv7-base:3.19
i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
diff --git a/samba/config.yaml b/samba/config.yaml
index cd06d249959..0b53621b9fc 100644
--- a/samba/config.yaml
+++ b/samba/config.yaml
@@ -1,10 +1,9 @@
---
-version: 12.3.1
+version: 12.5.4
slug: samba
name: Samba share
description: Expose Home Assistant folders with SMB/CIFS
url: https://github.com/home-assistant/addons/tree/master/samba
-codenotary: notary@home-assistant.io
arch:
- armhf
- armv7
@@ -27,7 +26,18 @@ options:
username: homeassistant
password: null
workgroup: WORKGROUP
+ local_master: true
+ enabled_shares:
+ - addons
+ - addon_configs
+ - backup
+ - config
+ - media
+ - share
+ - ssl
compatibility_mode: false
+ apple_compatibility_mode: true
+ server_signing: "default"
veto_files:
- ._*
- .DS_Store
@@ -45,7 +55,12 @@ schema:
username: str
password: password
workgroup: str
+ local_master: bool
+ enabled_shares:
+ - "match(^(?i:(addons|addon_configs|backup|config|media|share|ssl))$)"
compatibility_mode: bool
+ apple_compatibility_mode: bool
+ server_signing: list(default|auto|mandatory|disabled)
veto_files:
- str
allow_hosts:
diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run
index 3fc7a2ae763..bd94a670aca 100755
--- a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run
+++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run
@@ -1,4 +1,6 @@
#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Prepare the Samba service for running
# ==============================================================================
@@ -12,6 +14,8 @@ if ! bashio::config.has_value 'username' || ! bashio::config.has_value 'password
bashio::exit.nok "Setting a username and password is required!"
fi
+bashio::config.require "enabled_shares" "Samba is a tool for sharing folders. Starting it without sharing any folders defeats the purpose."
+
# Read hostname from API or setting default "hassio"
HOSTNAME=$(bashio::info.hostname)
if bashio::var.is_empty "${HOSTNAME}"; then
@@ -22,7 +26,10 @@ bashio::log.info "Hostname: ${HOSTNAME}"
# Get supported interfaces
for interface in $(bashio::network.interfaces); do
- interfaces+=("${interface}")
+ interface_enabled=$(bashio::network.enabled "${interface}")
+ if bashio::var.true "${interface_enabled}"; then
+ interfaces+=("${interface}")
+ fi
done
if [ ${#interfaces[@]} -eq 0 ]; then
bashio::exit.nok 'No supported interfaces found to bind on.'
@@ -30,7 +37,8 @@ fi
bashio::log.info "Interfaces: $(printf '%s ' "${interfaces[@]}")"
# Generate Samba configuration.
-jq ".interfaces = $(jq -c -n '$ARGS.positional' --args -- "${interfaces[@]}")" /data/options.json \
+jq ".interfaces = $(jq -c -n '$ARGS.positional' --args -- "${interfaces[@]}") |
+ .enabled_shares.[] |= ascii_downcase" /data/options.json \
| tempio \
-template /usr/share/tempio/smb.gtpl \
-out /etc/samba/smb.conf
diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish
index caf12de9d62..25b9f61011c 100755
--- a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish
+++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish
@@ -1,8 +1,10 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when nmbd fails
# ==============================================================================
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run
index ea8057041b9..74bb858e842 100755
--- a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run
+++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run
@@ -1,4 +1,6 @@
#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start nmbd service
# ==============================================================================
diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish
index 137f1e94061..e60184ba47e 100755
--- a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish
+++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish
@@ -1,8 +1,10 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when smbd fails
# ==============================================================================
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run
index 8f3d654782d..219d3d4ebfa 100755
--- a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run
+++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run
@@ -1,4 +1,6 @@
#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start smbd service
# ==============================================================================
diff --git a/samba/rootfs/usr/share/tempio/smb.gtpl b/samba/rootfs/usr/share/tempio/smb.gtpl
index 77e092047a7..6b00b14c387 100644
--- a/samba/rootfs/usr/share/tempio/smb.gtpl
+++ b/samba/rootfs/usr/share/tempio/smb.gtpl
@@ -2,9 +2,12 @@
netbios name = {{ env "HOSTNAME" }}
workgroup = {{ .workgroup }}
server string = Samba Home Assistant
+ local master = {{ .local_master | ternary "yes" "no" }}
security = user
ntlm auth = yes
+ idmap config * : backend = tdb
+ idmap config * : range = 1000000-2000000
load printers = no
disable spoolss = yes
@@ -12,7 +15,7 @@
log level = 1
bind interfaces only = yes
- interfaces = 127.0.0.1 {{ .interfaces | join " " }}
+ interfaces = lo {{ .interfaces | join " " }}
hosts allow = 127.0.0.1 {{ .allow_hosts | join " " }}
{{ if .compatibility_mode }}
@@ -23,7 +26,14 @@
mangled names = no
dos charset = CP850
unix charset = UTF-8
+
+ {{ if .apple_compatibility_mode }}
+ vfs objects = catia fruit streams_xattr
+ {{ end }}
+
+ server signing = {{ .server_signing }}
+{{ if (has "config" .enabled_shares) }}
[config]
browseable = yes
writeable = yes
@@ -34,7 +44,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "addons" .enabled_shares) }}
[addons]
browseable = yes
writeable = yes
@@ -45,7 +57,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "addon_configs" .enabled_shares) }}
[addon_configs]
browseable = yes
writeable = yes
@@ -56,7 +70,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "ssl" .enabled_shares) }}
[ssl]
browseable = yes
writeable = yes
@@ -67,7 +83,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "share" .enabled_shares) }}
[share]
browseable = yes
writeable = yes
@@ -78,7 +96,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "backup" .enabled_shares) }}
[backup]
browseable = yes
writeable = yes
@@ -89,7 +109,9 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
+{{ if (has "media" .enabled_shares) }}
[media]
browseable = yes
writeable = yes
@@ -100,3 +122,4 @@
force group = root
veto files = /{{ .veto_files | join "/" }}/
delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }}
+{{ end }}
diff --git a/samba/translations/en.yaml b/samba/translations/en.yaml
index d819acc9fb6..7fee4e38d10 100644
--- a/samba/translations/en.yaml
+++ b/samba/translations/en.yaml
@@ -11,10 +11,34 @@ configuration:
workgroup:
name: Workgroup
description: Change WORKGROUP to reflect your network needs.
+ local_master:
+ name: Local master
+ description: Enable to try and become a local master browser on a subnet.
+ enabled_shares:
+ name: >-
+ Enabled Shares - allowed values are:
+ addons, addon_configs, backup, config, media, share, or ssl.
+ description: >-
+ List of file shares to make available.
+ Adding a share requires typing its name to add it.
+ The listed values are the only allowed values.
+ The configuration cannot be saved if any non-allowed value is in the list.
compatibility_mode:
name: Enable Compatibility Mode
description: >-
- Enable this to use old legacy Samba protocols on the Samba add-on.
+ Enable this to use old legacy Samba protocols on the Samba app.
+ apple_compatibility_mode:
+ name: Enable Compatibility Settings for Apple Devices
+ description: >-
+ Enable Samba configurations to improve interoperability with Apple
+ devices. May cause issues with file systems that do not support xattr
+ such as exFAT.
+ server_signing:
+ name: Server signing
+ description: >-
+ Configure SMB server message signing requirements.
+ Refer to the smb.conf man page for more information.
+ Only change this if you know your SMB clients can support it.
veto_files:
name: Veto Files
description: List of files that are neither visible nor accessible.
diff --git a/silabs-multiprotocol/CHANGELOG.md b/silabs-multiprotocol/CHANGELOG.md
index b6bb7a35755..e62764a6018 100644
--- a/silabs-multiprotocol/CHANGELOG.md
+++ b/silabs-multiprotocol/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## 2.4.5
+- Support Home Assistant Connect ZBT-1.
+
## 2.4.4
- Revert back to Silicon Labs Gecko SDK 4.3.1 while 4.4.0 instability is investigated.
- Backport firmware modifications for improved stability.
diff --git a/silabs-multiprotocol/DOCS.md b/silabs-multiprotocol/DOCS.md
index 9cadc0ff2d6..b6a50301f77 100644
--- a/silabs-multiprotocol/DOCS.md
+++ b/silabs-multiprotocol/DOCS.md
@@ -1,25 +1,25 @@
-# Home Assistant Add-on: Silicon Labs Multiprotocol
+# Home Assistant App: Silicon Labs Multiprotocol
-**NOTE**: This add-on has the option to automatically install the right firmware for Home Assistant Yellow and Home Assistant SkyConnect. Follow [this guide](https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually) to change back to a firmware that is compatible with other Zigbee software.
+**NOTE**: This app (formerly known as app) has the option to automatically install the right firmware for Home Assistant Yellow, SkyConnect, and Connect ZBT-1. Follow [this guide](https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually) to change back to a firmware that is compatible with other Zigbee software.
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**.
-2. Find the "Silicon Labs Multiprotocol" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Silicon Labs Multiprotocol" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The add-on needs a Silicon Labs based wireless module accessible through a
+The app needs a Silicon Labs based wireless module accessible through a
serial port (like the module on Yellow or most USB based wireless adapters).
Once the firmware is loaded follow the following steps:
-1. Select the correct `device` in the add-on configuration tab and press `Save`.
+1. Select the correct `device` in the app configuration tab and press `Save`.
On Home Assistant Yellow use `/dev/ttyAMA1`.
-2. Start the add-on.
+2. Start the app.
**NOTE:** the Web frontend is only accessible when OpenThread is enabled (see below).
@@ -27,7 +27,7 @@ Once the firmware is loaded follow the following steps:
To use Zigbee with ZHA configure the Integration as follows:
-1. Remember/copy the hostname of the add-on (e.g. `c8f00288-silabs-multiprotocol`).
+1. Remember/copy the hostname of the app (e.g. `c8f00288-silabs-multiprotocol`).
2. Add the Zigbee Home Automation (ZHA) integration to Home Assistant Core
3. When asked for the Serial Device Path, choose `Enter Manually`.
4. Choose `EZSP` as Radio type.
@@ -38,11 +38,11 @@ To use Zigbee with ZHA configure the Integration as follows:
### OpenThread
-At this point OpenThread support is experimental. This add-on makes your Home
+At this point OpenThread support is experimental. This app makes your Home
Assistant installation an OpenThread Border Router (OTBR). A basic integration
for Home Assistant Core named `otbr` is currently in the making.
-To use the OTBR enable it in the Configuration tab and restart the add-on. Home
+To use the OTBR enable it in the Configuration tab and restart the app. Home
Assistant should discover the OpenThread border router automatically and
configure it as necessary.
@@ -50,7 +50,7 @@ configure it as necessary.
There is also a web interface provided by the OTBR. However, the web
interface has caveats (e.g. forming a network does not generate an off-mesh
-routable IPv6 prefix which causes changing IPv6 addressing on first add-on
+routable IPv6 prefix which causes changing IPv6 addressing on first app
restart). It is still possible to enable the web interface for debugging
purpose. Make sure to expose both the Web UI port and REST API port (the
latter needs to be on port 8081) on the host interface. To do so, click on
@@ -59,9 +59,9 @@ and 8081 in the OpenThread REST API port field).
### Automatic firmware upgrade
-If the `autoflash_firmware` configuration is set, the add-on will automatically
-install or update to the RCP Multi-PAN firmware if a Home Assistant SkyConnect
-or Home Assistant Yellow is detected.
+If the `autoflash_firmware` configuration is set, the app will automatically
+install or update to the RCP Multi-PAN firmware if a Home Assistant Connect ZBT-1/
+SkyConnect or Home Assistant Yellow is detected.
**NOTE:** Switching back to a Zigbee only (EmberZNet) firmware requires manual
steps currently. You can find a guide on the Nabu Casa Silicon Labs firmware
@@ -70,14 +70,14 @@ manually](https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-ra
## Configuration
-Add-on configuration:
+App configuration:
| Configuration | Description |
|--------------------|--------------------------------------------------------|
| device (mandatory) | Serial service where the Silicon Labs radio is attached |
| baudrate | Serial port baudrate (depends on firmware) |
| flow_control | If hardware flow control should be enabled (depends on firmware) |
-| autoflash_firmware | Automatically install/update firmware (Home Assistant SkyConnect/Yellow) |
+| autoflash_firmware | Automatically install/update firmware (Home Assistant Connect ZBT-1/SkyConnect/Yellow) |
| network_device | Host and port where CPC daemon can find the Silicon Labs radio (takes precedence over device) |
| cpcd_trace | Co-Processor Communication tracing (trace in log) |
| otbr_enable | Enable OpenThread BorderRouter |
@@ -86,10 +86,10 @@ Add-on configuration:
## Architecture
-The add-on runs several service internally. This architecture diagram shows what
-the add-on currently implements.
+The app runs several service internally. This architecture diagram shows what
+the app currently implements.
-
+
## Support
diff --git a/silabs-multiprotocol/Dockerfile b/silabs-multiprotocol/Dockerfile
index 3852a7fa2fa..77537c4e507 100644
--- a/silabs-multiprotocol/Dockerfile
+++ b/silabs-multiprotocol/Dockerfile
@@ -90,25 +90,33 @@ FROM --platform=linux/amd64 cross-builder-${BUILD_ARCH} AS zigbeed-builder
ARG GECKO_SDK_VERSION
+# Install and sanity check SLC CLI binary
RUN \
set -x \
&& apt-get install -y --no-install-recommends \
python3 \
python3-jinja2 \
python3-pip \
- openjdk-17-jre \
git-lfs \
+ gnupg \
unzip \
+ && curl -s https://repos.azul.com/azul-repo.key | gpg --dearmor -o /usr/share/keyrings/azul.gpg \
+ && echo "deb [signed-by=/usr/share/keyrings/azul.gpg] https://repos.azul.com/zulu/deb stable main" > /etc/apt/sources.list.d/zulu.list \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ zulu21-jre \
&& curl -O https://www.silabs.com/documents/login/software/slc_cli_linux.zip \
&& unzip slc_cli_linux.zip \
- && cd slc_cli/ && chmod +x slc
+ && cd slc_cli/ && chmod +x slc \
+ && ./slc --version
ENV PATH="/usr/src/slc_cli/:$PATH"
RUN \
set -x \
- && git clone --depth 1 -b ${GECKO_SDK_VERSION} \
- https://github.com/SiliconLabs/gecko_sdk.git
+ && curl -o gecko_sdk.zip -L https://github.com/SiliconLabs/gecko_sdk/releases/download/${GECKO_SDK_VERSION}/gecko-sdk.zip \
+ && unzip -q -d gecko_sdk gecko_sdk.zip \
+ && rm gecko_sdk.zip
# zigbeed links against libcpc.so
COPY --from=cpcd-builder /usr/local/ /usr/${DEBIAN_CROSS_PREFIX}/
diff --git a/silabs-multiprotocol/README.md b/silabs-multiprotocol/README.md
index 080b9bcac11..14c3bb9b7ce 100644
--- a/silabs-multiprotocol/README.md
+++ b/silabs-multiprotocol/README.md
@@ -1,10 +1,11 @@
-# Home Assistant Add-on: SiliconLabs Zigbee/OpenThread Multiprotocol Add-on
+> [!CAUTION]
+> Multiprotocol is no longer supported and will be removed in the near future!
+> [Disable multiprotocol support](https://connectzbt1.home-assistant.io/procedures/disable-multiprotocol/) by migrating your radio back to Zigbee or Thread firmware.
-Zigbee/OpenThread Multiprotocol container for Silicon Labs based radios such as
-Home Assistant Yellow or Home Assistant SkyConnect.
+# \[DEPRECATED\] Home Assistant App: SiliconLabs Zigbee/OpenThread Multiprotocol App
-**NOTE:** Use System -> Hardware -> Configure to enable Multiprotocol support
-seamlessly.
+Zigbee/OpenThread Multiprotocol container for Silicon Labs based radios such as
+Home Assistant Yellow, Home Assistant SkyConnect, and Home Assistant Connect ZBT-1.
![Supports armv7 Architecture][armv7-shield]
![Supports aarch64 Architecture][aarch64-shield]
@@ -12,7 +13,7 @@ seamlessly.
## About
-This add-on allows you to use Zigbee and OpenThread protocol simultaneous on a
+This app (formerly known as add-on) allows you to use Zigbee and OpenThread protocol simultaneous on a
single Silicon Labs based radio. The radio needs the RCP Multi-PAN firmware
installed to support multiple IEEE 802.15.4 Personal Area Networks (PAN). The
addon has been tested with EFR32 Series 2 based radios.
diff --git a/silabs-multiprotocol/build.yaml b/silabs-multiprotocol/build.yaml
index b6983d81fbd..eced3a05365 100644
--- a/silabs-multiprotocol/build.yaml
+++ b/silabs-multiprotocol/build.yaml
@@ -6,4 +6,4 @@ build_from:
args:
CPCD_VERSION: v4.3.1
GECKO_SDK_VERSION: v4.3.1
- UNIVERSAL_SILABS_FLASHER: 0.0.17
+ UNIVERSAL_SILABS_FLASHER: 0.0.31
diff --git a/silabs-multiprotocol/config.yaml b/silabs-multiprotocol/config.yaml
index 2ee042e5de4..675288ef698 100644
--- a/silabs-multiprotocol/config.yaml
+++ b/silabs-multiprotocol/config.yaml
@@ -1,7 +1,7 @@
---
-version: 2.4.4
+version: 2.4.5
slug: silabs_multiprotocol
-name: Silicon Labs Multiprotocol
+name: "Silicon Labs Multiprotocol [deprecated]"
description: Zigbee and OpenThread multiprotocol add-on
url: >
https://github.com/home-assistant/addons/tree/master/silabs-multiprotocol
@@ -50,5 +50,5 @@ schema:
otbr_enable: bool
otbr_log_level: list(debug|info|notice|warning|error|critical|alert|emergency)
otbr_firewall: bool
-stage: experimental
+stage: deprecated
startup: services
diff --git a/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh b/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh
index 30ae7d753b1..318970c6764 100755
--- a/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh
+++ b/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Check that no other CPC instance is running on this system
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish
index ea4790f9963..89abb4b2c6b 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Take down the container if cpcd exits
# ==============================================================================
@@ -6,6 +8,7 @@ bashio::log.info "CPC ended with exit code ${1} (signal ${2})..."
rm -r /dev/shm/cpcd
+# shellcheck disable=SC2086
if [ ${1} -ne 0 ] && [ ${1} -ne 256 ]; then
/run/s6/basedir/bin/halt
fi
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run
index b85f3e94670..97f737aee39 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start Co-Processor Communication Daemon (CPCd)
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
index 208999d7977..92b89c6b491 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# mDNSResponder finish script
#==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
index 4d80c10f1da..6affe2c5577 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start mDNSResponder daemon
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
index 222ad7dd9cb..78a78bf56f8 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
@@ -1,10 +1,13 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# OpenThread BorderRouter Daemon finish script
#==============================================================================
bashio::log.info "otbr-agent ended with exit code ${1} (signal ${2})..."
+# shellcheck disable=SC1091
. /etc/s6-overlay/scripts/otbr-agent-common
ipset_destroy_if_exist()
@@ -16,12 +19,17 @@ ipset_destroy_if_exist()
done
}
+# shellcheck disable=SC2086,SC2154
while ip6tables -C FORWARD -o $thread_if -j $otbr_forward_ingress_chain 2> /dev/null; do
+ # shellcheck disable=SC2086
ip6tables -D FORWARD -o $thread_if -j $otbr_forward_ingress_chain
done
+# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_ingress_chain 2> /dev/null; then
+ # shellcheck disable=SC2086
ip6tables -w -F $otbr_forward_ingress_chain
+ # shellcheck disable=SC2086
ip6tables -w -X $otbr_forward_ingress_chain
fi
@@ -30,12 +38,17 @@ ipset_destroy_if_exist otbr-ingress-deny-src-swap
ipset_destroy_if_exist otbr-ingress-allow-dst
ipset_destroy_if_exist otbr-ingress-allow-dst-swap
+# shellcheck disable=SC2086,SC2154
while ip6tables -C FORWARD -i $thread_if -j $otbr_forward_egress_chain 2> /dev/null; do
+ # shellcheck disable=SC2086
ip6tables -D FORWARD -i $thread_if -j $otbr_forward_egress_chain
done
+# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_egress_chain 2> /dev/null; then
+ # shellcheck disable=SC2086
ip6tables -w -F $otbr_forward_egress_chain
+ # shellcheck disable=SC2086
ip6tables -w -X $otbr_forward_egress_chain
fi
bashio::log.info "OTBR firewall teardown completed."
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
index 1fd0b29ee76..b3bb2f7067c 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
@@ -1,13 +1,19 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# OpenThread BorderRouter start script
# ==============================================================================
+# shellcheck disable=SC1091
. /etc/s6-overlay/scripts/otbr-agent-common
declare backbone_if
+# shellcheck disable=SC2034
declare device
+# shellcheck disable=SC2034
declare baudrate
+# shellcheck disable=SC2034
declare flow_control
declare otbr_log_level
declare otbr_log_level_int
@@ -47,11 +53,13 @@ case "${otbr_log_level}" in
;;
esac
+# shellcheck disable=SC2086
if [ -z ${backbone_if} ]; then
bashio::log.warning "No primary network interface found! Using static eth0."
backbone_if="eth0"
fi
+# shellcheck disable=SC2015
mkdir -p /data/thread && ln -sft /var/lib /data/thread || bashio::exit.nok "Could not create directory /var/lib/thread to store Thread data."
if bashio::config.true 'otbr_firewall'; then
@@ -61,17 +69,27 @@ if bashio::config.true 'otbr_firewall'; then
ipset create -exist otbr-ingress-allow-dst hash:net family inet6
ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6
+ # shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_ingress_chain
+ # shellcheck disable=SC2086,SC2154
ip6tables -I FORWARD 1 -o $thread_if -j $otbr_forward_ingress_chain
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -i ${thread_if} -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-deny-src src -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -j DROP
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -j ACCEPT
+ # shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_egress_chain
+ # shellcheck disable=SC2086
ip6tables -I FORWARD 2 -i $thread_if -j $otbr_forward_egress_chain
+ # shellcheck disable=SC2086
ip6tables -A $otbr_forward_egress_chain -j ACCEPT
else
# Make sure ip6tables (as used by Docker) allow IP forwarding
@@ -97,6 +115,7 @@ echo "${otbr_rest_listen}" > /tmp/otbr-agent-rest-api
echo "${otbr_rest_listen_port}" >> /tmp/otbr-agent-rest-api
bashio::log.info "Starting otbr-agent..."
+# shellcheck disable=SC2086
exec s6-notifyoncheck -d -s 300 -w 300 -n 0 \
"/usr/sbin/otbr-agent" -I ${thread_if} -B "${backbone_if}" \
--rest-listen-address "${otbr_rest_listen}" \
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
index 2c9cd489043..2035d588936 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# OpenThread BorderRouter web interface finish script
#==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
index 53fc7e616a0..8d82419865d 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start OpenThread BorderRouter web interface
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run
index ad24d16c4ce..5d3127a066f 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start socat TCP client for CPC daemon
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish
index 3e18c7d6c83..4dbf2fbea29 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
#==============================================================================
# EmberZNet Zigbee Daemon finish script
#==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run
index 3389e4f546f..56683e5f0f8 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run
@@ -1,7 +1,10 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start EmberZNet Zigbee Daemon
# ==============================================================================
+# shellcheck disable=SC2015
mkdir -p /data/zigbeed && cd /data/zigbeed || bashio::exit.nok "Could not change to zigbeed working directory"
ezsp_listen="::"
@@ -14,6 +17,7 @@ if ! bashio::var.has_value "${ezsp_listen_port}"; then
fi
bashio::log.info "Starting zigbeed..."
+# shellcheck disable=SC2086
exec /usr/local/bin/zigbeed --radio-url "spinel+cpc://cpcd_0?iid=1&iid-list=0" \
--ezsp-listen ${ezsp_listen} \
--ezsp-listen-port ${ezsp_listen_port}
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh
index 37a8218fdf5..074dc4179e5 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: Base Images
# Displays a simple add-on banner on startup
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up
index 9791f90b7a7..48793059b20 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Generate Silicon Labs Multiprotocol configurations
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
index 7377f674867..bc3ef5d28fa 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Send OTBR discovery information to Home Assistant
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh
index e6c253c68e2..8cd2c2d30dc 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Disable OTBR if not enabled
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh
index 81c685a6255..6166b077da2 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Enable socat-cpcd-tcp service if needed
# ==============================================================================
diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
index 1c55bfb58d7..a8410b36f18 100755
--- a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
+++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
@@ -1,8 +1,11 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start universal-silabs-flasher if requested
# ==============================================================================
+# shellcheck disable=SC2034
declare autoflash_firmware
declare device
declare firmware
@@ -30,6 +33,7 @@ if [ -d /sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1 ] && [ "${device}"
gpio_reset_flag="--yellow-gpio-reset"
else
# Check device manufacturer/product information
+ # shellcheck disable=SC2046,SC2086
usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}))/../../../../)
if [ ! -f "${usb_device_path}/idProduct" ]; then
bashio::log.info "The selected serial port is not a USB device."
@@ -47,6 +51,8 @@ else
bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}."
if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then
firmware="NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl"
+ elif [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "Home Assistant Connect ZBT-1"* ]]; then
+ firmware="NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl"
else
exit_no_firmware
fi
@@ -57,5 +63,6 @@ fi
echo 460800 > /tmp/known-baudrate
bashio::log.info "Starting universal-silabs-flasher with ${device}"
+# shellcheck disable=SC2086
exec universal-silabs-flasher --device ${device} \
flash ${gpio_reset_flag} --ensure-exact-version --allow-cross-flashing --firmware "/root/${firmware}"
diff --git a/silabs_flasher/CHANGELOG.md b/silabs_flasher/CHANGELOG.md
index 5a0c4d6a384..e7bf37f8426 100644
--- a/silabs_flasher/CHANGELOG.md
+++ b/silabs_flasher/CHANGELOG.md
@@ -1,5 +1,42 @@
# Changelog
+## 0.4.0
+
+- Upgrade to Alpine 3.22
+- Update universal-silabs-flasher to v0.0.36
+
+## 0.3.4
+
+- Make custom ezsp baudrate a truly optional configuration
+
+## 0.3.3
+
+- Allow to start universal-silabs-flasher with custom ezsp baudrate
+
+## 0.3.2
+
+- Update flasher script to work with Home Assistant Yellow with CM5
+
+## 0.3.1
+- Update firmwares to EmberZNet 7.4.4
+- Update universal-silabs-flasher to v0.0.25
+
+## 0.3.0
+- Update firmwares to EmberZNet 7.4.3
+- Update universal-silabs-flasher to v0.0.22
+
+## 0.2.3
+
+- Upgrade to Alpine 3.19
+
+## 0.2.2
+
+- Update universal-silabs-flasher to v0.0.19
+
+## 0.2.1
+
+- Support flashing the Connect ZBT-1.
+
## 0.2.0
- Update universal-silabs-flasher to v0.0.13
diff --git a/silabs_flasher/DOCS.md b/silabs_flasher/DOCS.md
index 3269615cab4..3b164c796a3 100644
--- a/silabs_flasher/DOCS.md
+++ b/silabs_flasher/DOCS.md
@@ -1,32 +1,33 @@
-# Home Assistant Add-on: Silicon Labs Flasher Add-on
+# Home Assistant App: Silicon Labs Flasher App
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**.
-2. Find the "Silicon Labs Flasher" add-on and click it.
+1. Navigate in your Home Assistant frontend to **Settings** > **Apps** > **App Store**.
+2. Find the "Silicon Labs Flasher" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The add-on needs a Silicon Labs based wireless module accessible through a
+The app needs a Silicon Labs based wireless module accessible through a
serial port (like the module on Home Assistant Yellow, Home Assistant
-SkyConnect or other USB based wireless adapters).
+SkyConnect/ZBT-1 or other USB based wireless adapters).
-1. Select the correct `device` in the add-on configuration tab and press `Save`.
-2. Start the add-on.
+1. Select the correct `device` in the app configuration tab and press `Save`.
+2. Start the app.
## Configuration
-Add-on configuration:
+App configuration:
-| Configuration | Description |
-|--------------------|--------------------------------------------------------|
-| device (mandatory) | Serial service where the Silicon Labs radio is attached |
-| baudrate | Serial port baudrate (depends on firmware) |
-| flow_control | If hardware flow control should be enabled (depends on firmware) |
-| firmware_url | Custom URL to flash firmware from |
+| Configuration | Description |
+|---------------------|--------------------------------------------------------|
+| device (mandatory) | Serial service where the Silicon Labs radio is attached |
+| bootloader_baudrate | Serial port baudrate for gecko bootloader (depends on firmware) |
+| ezsp_baudrate | Serial port baudrate for ezsp (depends on firmware) |
+| flow_control | If hardware flow control should be enabled (depends on firmware) |
+| firmware_url | Custom URL to flash firmware from |
## Support
diff --git a/silabs_flasher/Dockerfile b/silabs_flasher/Dockerfile
index e5c8a033563..ccfc3cd3714 100644
--- a/silabs_flasher/Dockerfile
+++ b/silabs_flasher/Dockerfile
@@ -13,7 +13,6 @@ RUN \
&& pip3 install \
--no-cache-dir \
--prefer-binary \
- --find-links "https://wheels.home-assistant.io/musllinux/${BUILD_ARCH}/" \
universal-silabs-flasher=="${UNIVERSAL_SILABS_FLASHER}"
COPY rootfs /
diff --git a/silabs_flasher/README.md b/silabs_flasher/README.md
index e8587a72d62..56c39c8ed9c 100644
--- a/silabs_flasher/README.md
+++ b/silabs_flasher/README.md
@@ -1,13 +1,13 @@
-# Home Assistant Add-on: Silicon Labs Flasher Add-on
+# Home Assistant App: Silicon Labs Flasher App
-Silicon Labs Flasher add-on to flash Silicon Labs based radios.
+Silicon Labs Flasher app (formerly known as add-on) to flash Silicon Labs based radios.
-By default this add-on flashes the firmware to use Zigbee (Silicon
+By default this app flashes the firmware to use Zigbee (Silicon
Labs EmberZNet Zigbee stack).
-**NOTE:** Make sure no other add-on or integration is using the radio. In
+**NOTE:** Make sure no other app or integration is using the radio. In
particular disable the Zigbee Home Automation integration and the Silicon Labs
-Multiprotocol add-on.
+Multiprotocol app.
![Supports aarch64 Architecture][aarch64-shield]
![Supports amd64 Architecture][amd64-shield]
@@ -17,8 +17,8 @@ Multiprotocol add-on.
## About
-This add-on allows you to flash firmwares using the Gecko Bootloader file format
-(gbl). By default it comes with firmware for Home Assistant SkyConnect and
+This app allows you to flash firmwares using the Gecko Bootloader file format
+(gbl). By default it comes with firmware for Home Assistant SkyConnect/ZBT-1 and
Home Assistant Yellow to flash Zigbee.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
diff --git a/silabs_flasher/build.yaml b/silabs_flasher/build.yaml
index b2d1dc81f29..b6801ac71d3 100644
--- a/silabs_flasher/build.yaml
+++ b/silabs_flasher/build.yaml
@@ -1,9 +1,9 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.17
- amd64: ghcr.io/home-assistant/amd64-base-python:3.11-alpine3.17
- armhf: ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.17
- armv7: ghcr.io/home-assistant/armv7-base-python:3.11-alpine3.17
- i386: ghcr.io/home-assistant/i386-base-python:3.11-alpine3.17
+ aarch64: ghcr.io/home-assistant/aarch64-base-python:3.13-alpine3.22
+ amd64: ghcr.io/home-assistant/amd64-base-python:3.13-alpine3.22
+ armhf: ghcr.io/home-assistant/armhf-base-python:3.13-alpine3.22
+ armv7: ghcr.io/home-assistant/armv7-base-python:3.13-alpine3.22
+ i386: ghcr.io/home-assistant/i386-base-python:3.13-alpine3.22
args:
- UNIVERSAL_SILABS_FLASHER: 0.0.13
+ UNIVERSAL_SILABS_FLASHER: 0.0.36
diff --git a/silabs_flasher/config.yaml b/silabs_flasher/config.yaml
index 29b8d019d4a..b8010e651c0 100644
--- a/silabs_flasher/config.yaml
+++ b/silabs_flasher/config.yaml
@@ -1,5 +1,5 @@
---
-version: 0.2.0
+version: 0.4.0
slug: silabs_flasher
name: Silicon Labs Flasher
description: Silicon Labs firmware flasher add-on
@@ -23,6 +23,7 @@ options:
schema:
device: device(subsystem=tty)?
bootloader_baudrate: list(57600|115200|230400|460800|921600)
+ ezsp_baudrate: int?
flow_control: bool?
firmware_url: str?
verbose: bool?
diff --git a/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh b/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh
index 37a8218fdf5..074dc4179e5 100755
--- a/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh
+++ b/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: Base Images
# Displays a simple add-on banner on startup
diff --git a/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
index 9e3cedc56cb..1094e3b9ed2 100755
--- a/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
+++ b/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up
@@ -1,10 +1,13 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start universal-silabs-flasher
# ==============================================================================
set -e
+# shellcheck disable=SC2034
declare autoflash_firmware
declare device
declare bootloader_baudrate
@@ -30,12 +33,32 @@ function exit_no_firmware {
exit 0
}
+# Function to check if the device is Home Assistant Yellow
+function is_home_assistant_yellow {
+ # First, ensure the device is /dev/ttyAMA1
+ if [ "${device}" != "/dev/ttyAMA1" ]; then
+ return 1
+ fi
+
+ # Check the known paths for Home Assistant Yellow
+ local paths=(
+ "/sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1"
+ "/sys/devices/platform/axi/1000120000.pcie/1f0003c000.serial/tty/ttyAMA1"
+ )
+ for path in "${paths[@]}"; do
+ if [ -d "${path}" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
device=$(bashio::config 'device')
bootloader_baudrate=$(bashio::config 'bootloader_baudrate')
-if [ -d /sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1 ] && [ "${device}" == "/dev/ttyAMA1" ]; then
+if is_home_assistant_yellow; then
bashio::log.info "Detected Home Assistant Yellow"
- gpio_reset_flag="--yellow-gpio-reset"
+ gpio_reset_flag="--bootloader-reset yellow"
else
gpio_reset_flag=""
fi
@@ -50,10 +73,11 @@ if bashio::config.has_value 'firmware_url'; then
firmware="firmware.gbl"
else
# Assume to run on Yellow if UART4 is mapped to ttyAMA1
- if [ -d /sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1 ] && [ "${device}" == "/dev/ttyAMA1" ]; then
- firmware="NabuCasa_Yellow_EZSP_v7.3.1.0_PA32_ncp-uart-hw_115200.gbl"
+ if is_home_assistant_yellow; then
+ firmware="yellow_zigbee_ncp_7.4.4.0.gbl"
else
# Check device manufacturer/product information
+ # shellcheck disable=SC2046,SC2086
usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}) | sed 's:/[^/]*tty[^/]*::g' )/../)
if [ ! -f "${usb_device_path}/idProduct" ]; then
bashio::log.info "The selected serial port is not a USB device."
@@ -70,7 +94,9 @@ else
bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}."
if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then
- firmware="NabuCasa_SkyConnect_EZSP_v7.3.1.0_ncp-uart-hw_115200.gbl"
+ firmware="skyconnect_zigbee_ncp_7.4.4.0.gbl"
+ elif [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "Home Assistant Connect ZBT-1"* ]]; then
+ firmware="skyconnect_zigbee_ncp_7.4.4.0.gbl"
else
exit_no_firmware
fi
@@ -83,9 +109,18 @@ if bashio::config.true 'verbose'; then
verbose="-v"
fi
-bashio::log.info "Starting universal-silabs-flasher with ${device} (bootloader baudrate ${bootloader_baudrate})"
-universal-silabs-flasher ${verbose} --device ${device} \
- --bootloader-baudrate "${bootloader_baudrate}" \
- flash ${gpio_reset_flag} --force --firmware "/root/${firmware}"
-
+declare -a ezsp_baudrate_arg=()
+if bashio::config.has_value 'ezsp_baudrate'; then
+ baud="$(bashio::config 'ezsp_baudrate')"
+ ezsp_baudrate_arg=(--ezsp-baudrate "$baud")
+fi
+bashio::log.info "Starting universal-silabs-flasher with ${device} (bootloader baudrate ${bootloader_baudrate})"
+# shellcheck disable=SC2086
+universal-silabs-flasher \
+ ${verbose} \
+ --device ${device} \
+ --bootloader-baudrate "${bootloader_baudrate}" \
+ "${ezsp_baudrate_arg[@]}" \
+ ${gpio_reset_flag} \
+ flash --force --firmware "/root/${firmware}"
diff --git a/silabs_flasher/rootfs/root/NabuCasa_SkyConnect_EZSP_v7.3.1.0_ncp-uart-hw_115200.gbl b/silabs_flasher/rootfs/root/NabuCasa_SkyConnect_EZSP_v7.3.1.0_ncp-uart-hw_115200.gbl
deleted file mode 100644
index 03d0905111f..00000000000
Binary files a/silabs_flasher/rootfs/root/NabuCasa_SkyConnect_EZSP_v7.3.1.0_ncp-uart-hw_115200.gbl and /dev/null differ
diff --git a/silabs_flasher/rootfs/root/NabuCasa_Yellow_EZSP_v7.3.1.0_PA32_ncp-uart-hw_115200.gbl b/silabs_flasher/rootfs/root/NabuCasa_Yellow_EZSP_v7.3.1.0_PA32_ncp-uart-hw_115200.gbl
deleted file mode 100644
index cfbd65bddb0..00000000000
Binary files a/silabs_flasher/rootfs/root/NabuCasa_Yellow_EZSP_v7.3.1.0_PA32_ncp-uart-hw_115200.gbl and /dev/null differ
diff --git a/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl b/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl
new file mode 100644
index 00000000000..bce7aec4eae
Binary files /dev/null and b/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl differ
diff --git a/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl b/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl
new file mode 100644
index 00000000000..14a8f5e9490
Binary files /dev/null and b/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl differ
diff --git a/silabs_flasher/translations/en.yaml b/silabs_flasher/translations/en.yaml
index 3a8065549fd..9f07e2dbfa9 100644
--- a/silabs_flasher/translations/en.yaml
+++ b/silabs_flasher/translations/en.yaml
@@ -8,6 +8,11 @@ configuration:
description: >-
The serial port baudrate used to communicate with the Silicon Labs radio
in bootloader mode.
+ ezsp_baudrate:
+ name: EZSP Baudrate
+ description: >-
+ The serial port baudrate used to communicate with the Silicon Labs radio
+ in ezsp mode.
flow_control:
name: Hardware flow control
description: Enable hardware flow control for serial port.
diff --git a/speech_to_phrase/CHANGELOG.md b/speech_to_phrase/CHANGELOG.md
new file mode 100644
index 00000000000..5e47e032512
--- /dev/null
+++ b/speech_to_phrase/CHANGELOG.md
@@ -0,0 +1,36 @@
+# Changelog
+
+## 1.4.1
+
+- More robust parsing of `ask_question` answers from Home Assistant
+- Remove intent probability normalization
+- Revert to Kneser-Ney smoothing instead of Witten-Bell
+- Re-add German timer sentences
+
+## 1.4.0
+
+- Load answers from `assist_satellite.ask_question` in automations and scripts
+- Initial support for Catalan, Czech, Greek, Basque, Romanian, Portuguese, Russian, Polish, Hindi, Persian, Finnish, Mongolian, Slovenian, Swahili, and Turkish
+- Rebalance sentence probabilities to reduce number confusion
+- Timer minutes step by 5 instead of 10 after 20
+
+## 1.3.0
+
+- Add Coqui STT
+- Support range fractions in custom sentences (https://github.com/OHF-Voice/speech-to-phrase/issues/5)
+- Do full re-train at startup (https://github.com/OHF-Voice/speech-to-phrase/issues/11)
+- Remove websocket command message limit (https://github.com/OHF-Voice/speech-to-phrase/issues/6)
+- Bump `unicode-rbnf` to 2.3.0 (https://github.com/OHF-Voice/speech-to-phrase/issues/15)
+
+## 1.2.0
+
+- Split words on dashes `-` and underscores `_`
+- Remove template syntax from names (`[]<>{}()`)
+
+## 1.1.0
+
+- Add custom sentences
+
+## 1.0.0
+
+- Initial release
diff --git a/speech_to_phrase/DOCS.md b/speech_to_phrase/DOCS.md
new file mode 100644
index 00000000000..92a964a65dc
--- /dev/null
+++ b/speech_to_phrase/DOCS.md
@@ -0,0 +1,74 @@
+# Home Assistant App: Speech to phrase
+
+## Installation
+
+Follow these steps to get the app (formerly known as add-on) installed on your system:
+
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Speech to phrase" app and click it.
+3. Click on the "INSTALL" button.
+
+## How to use
+
+After this app is installed and running, it should automatically train itself based on your [exposed][] entities, areas, floors, and [sentence triggers][sentence trigger].
+The app will automatically re-train if necessary.
+
+The app will be automatically discovered by the Wyoming integration in Home Assistant. To finish the setup, click the following my button:
+
+[](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming)
+
+Alternatively, you can install the Wyoming integration manually, see the
+[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/)
+for more information.
+
+### Voice commands
+
+See [available voice commands](https://github.com/OHF-Voice/speech-to-phrase/blob/main/SENTENCES.md)
+
+### Custom sentences
+
+You can add [custom sentences][] to `/share/speech-to-phrase/custom_sentences//sentences.yaml` where `` is:
+
+* `ca` - Catalan
+* `cs` - Czech
+* `de` - German
+* `el` - Greek
+* `en` - English
+* `es` - Spanish
+* `eu` - Basque
+* `fa` - Persian/Farsi
+* `fi` - Finnish
+* `fr` - French
+* `hi` - Hindi
+* `it` - Italian
+* `mn` - Mongolian
+* `nl` - Dutch
+* `pl` - Polish
+* `pt_PT` - Portuguese
+* `ro` - Romanian
+* `ru` - Russian
+* `sl` - Slovenian
+* `sw` - Swahili
+* `tr` - Turkish
+
+## Support
+
+Got questions?
+
+You have several options to get them answered:
+
+- The [Home Assistant Discord Chat Server][discord].
+- The Home Assistant [Community Forum][forum].
+- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
+
+In case you've found an bug, please [open an issue on our GitHub][issue].
+
+[discord]: https://discord.gg/c5DvZ4e
+[forum]: https://community.home-assistant.io
+[issue]: https://github.com/home-assistant/addons/issues
+[reddit]: https://reddit.com/r/homeassistant
+[repository]: https://github.com/hassio-addons/repository
+
+[sentence trigger]: https://www.home-assistant.io/docs/automation/trigger/#sentence-trigger
+[exposed]: https://www.home-assistant.io/voice_control/voice_remote_expose_devices/
+[custom sentences]: https://github.com/OHF-voice/speech-to-phrase?tab=readme-ov-file#custom-sentences
diff --git a/speech_to_phrase/Dockerfile b/speech_to_phrase/Dockerfile
new file mode 100644
index 00000000000..7e7d7db3433
--- /dev/null
+++ b/speech_to_phrase/Dockerfile
@@ -0,0 +1,46 @@
+ARG BUILD_FROM
+FROM ${BUILD_FROM}
+ARG BUILD_ARCH
+
+# Set shell
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+# Install speech-to-phrase
+ARG SPEECH_TO_PHRASE_VERSION
+WORKDIR /usr/src
+
+RUN mkdir -p ./tools
+
+RUN \
+ apt-get update \
+ && apt-get install -y --no-install-recommends \
+ netcat-traditional \
+ python3 \
+ python3-pip \
+ python3-dev \
+ python3-venv \
+ build-essential \
+ curl \
+ libopenblas0 \
+ libencode-perl \
+ && ARCH="${BUILD_ARCH}" \
+ && if [[ "${BUILD_ARCH}" = "aarch64" ]]; then ARCH="arm64"; fi \
+ && curl --location --output - \
+ "https://huggingface.co/datasets/rhasspy/rhasspy-speech/resolve/main/tools/rhasspy-speech_${ARCH}.tar.gz?download=true" | \
+ tar -C ./tools -xzf - \
+ && python3 -m venv .venv \
+ && .venv/bin/pip3 install --no-cache-dir \
+ "speech-to-phrase @ https://github.com/OHF-Voice/speech-to-phrase/archive/refs/tags/v${SPEECH_TO_PHRASE_VERSION}.tar.gz" \
+ && apt-get remove --yes build-essential \
+ && apt-get autoclean \
+ && apt-get purge \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /
+COPY rootfs /
+
+HEALTHCHECK --start-period=10m \
+ CMD echo '{ "type": "describe" }' \
+ | nc -w 1 localhost 10300 \
+ | grep -iq "speech-to-phrase" \
+ || exit 1
diff --git a/speech_to_phrase/README.md b/speech_to_phrase/README.md
new file mode 100644
index 00000000000..4398d9d6455
--- /dev/null
+++ b/speech_to_phrase/README.md
@@ -0,0 +1,18 @@
+# Home Assistant App: Speech to phrase
+
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
+
+A fast and local speech-to-text system that is personalized with the names of things in your home.
+[Speech-to-phrase](https://github.com/OHF-voice/speech-to-phrase) is targeted at lower-end hardware, such as the Raspberry Pi 4 and Home Assistant Green.
+
+See the [documentation](http://github.com/OHF-voice/speech-to-phrase) for available voice commands.
+
+Built on top of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/).
+
+Requires Home Assistant 2023.11 or later.
+
+[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
+[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
+[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg
+[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg
+[i386-shield]: https://img.shields.io/badge/i386-no-red.svg
diff --git a/speech_to_phrase/build.yaml b/speech_to_phrase/build.yaml
new file mode 100644
index 00000000000..7116ce093db
--- /dev/null
+++ b/speech_to_phrase/build.yaml
@@ -0,0 +1,6 @@
+---
+build_from:
+ amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
+args:
+ SPEECH_TO_PHRASE_VERSION: 1.4.1
diff --git a/speech_to_phrase/config.yaml b/speech_to_phrase/config.yaml
new file mode 100644
index 00000000000..16045e1e8f0
--- /dev/null
+++ b/speech_to_phrase/config.yaml
@@ -0,0 +1,25 @@
+---
+version: 1.4.1
+slug: speech-to-phrase
+name: Speech-to-Phrase
+description: Fast and personalized local speech-to-text
+url: http://github.com/OHF-voice/speech-to-phrase
+arch:
+ - amd64
+ - aarch64
+init: false
+discovery:
+ - wyoming
+map:
+ - share:rw
+backup_exclude:
+ - "*/models/*"
+homeassistant_api: true
+options:
+ debug_logging: false
+schema:
+ debug_logging: bool
+ports:
+ "10300/tcp": null
+homeassistant: 2023.11.0
+image: homeassistant/{arch}-addon-speech-to-phrase
diff --git a/speech_to_phrase/icon.png b/speech_to_phrase/icon.png
new file mode 100644
index 00000000000..1013d7fcdb7
Binary files /dev/null and b/speech_to_phrase/icon.png differ
diff --git a/speech_to_phrase/logo.png b/speech_to_phrase/logo.png
new file mode 100644
index 00000000000..5e965abbe3a
Binary files /dev/null and b/speech_to_phrase/logo.png differ
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/speech-to-phrase b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/speech-to-phrase
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
new file mode 100755
index 00000000000..9bd21d640de
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
@@ -0,0 +1,24 @@
+#!/command/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Sends discovery information to Home Assistant.
+# ==============================================================================
+declare config
+
+# Wait for speech-to-phrase to become available
+bash -c \
+ "until
+ echo '{ \"type\": \"describe\" }'
+ > /dev/tcp/localhost/10300; do sleep 0.5;
+ done" > /dev/null 2>&1 || true;
+
+config=$(\
+ bashio::var.json \
+ uri "tcp://$(hostname):10300" \
+)
+
+if bashio::discovery "wyoming" "${config}" > /dev/null; then
+ bashio::log.info "Successfully sent discovery information to Home Assistant."
+else
+ bashio::log.error "Discovery message to Home Assistant failed!"
+fi
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type
new file mode 100644
index 00000000000..3d92b15f2d5
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type
@@ -0,0 +1 @@
+oneshot
\ No newline at end of file
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up
new file mode 100755
index 00000000000..31b0a0205b5
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up
@@ -0,0 +1 @@
+/etc/s6-overlay/s6-rc.d/discovery/run
\ No newline at end of file
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/dependencies.d/base b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/dependencies.d/base
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish
new file mode 100755
index 00000000000..1c046b21855
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish
@@ -0,0 +1,26 @@
+#!/command/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Take down the S6 supervision tree when service fails
+# s6-overlay docs: https://github.com/just-containers/s6-overlay
+# ==============================================================================
+# 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/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run
new file mode 100755
index 00000000000..c161807ef21
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run
@@ -0,0 +1,40 @@
+#!/command/with-contenv bashio
+# shellcheck shell=bash
+# ==============================================================================
+# Start speech-to-phrase service
+# ==============================================================================
+cd /usr/src || exit 1
+
+flags=()
+
+if bashio::config.has_value 'hass_websocket_uri'; then
+ hass_websocket_uri="$(bashio::config 'hass_websocket_uri')"
+else
+ hass_websocket_uri='ws://supervisor/core/websocket'
+fi
+
+if bashio::config.has_value 'hass_token'; then
+ hass_token="$(bashio::config 'hass_token')"
+else
+ hass_token="${SUPERVISOR_TOKEN}"
+fi
+
+if bashio::config.true 'debug_logging'; then
+ flags+=('--debug')
+fi
+
+models_dir='/data/models'
+mkdir -p "${models_dir}"
+
+# shellcheck disable=SC2068
+exec .venv/bin/python3 -m speech_to_phrase \
+ --uri 'tcp://0.0.0.0:10300' \
+ --tools-dir /usr/src/tools \
+ --train-dir /share/speech-to-phrase/train \
+ --models-dir "${models_dir}" \
+ --retrain-on-start \
+ --retrain-on-connect \
+ --retrain-seconds 300 \
+ --custom-sentences-dir /share/speech-to-phrase/custom_sentences \
+ --hass-token "${hass_token}" \
+ --hass-websocket-uri "${hass_websocket_uri}" ${flags[@]}
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type
new file mode 100644
index 00000000000..1780f9f44ef
--- /dev/null
+++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/speech-to-phrase b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/speech-to-phrase
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/speech_to_phrase/translations/en.yaml b/speech_to_phrase/translations/en.yaml
new file mode 100644
index 00000000000..31c8cf2c313
--- /dev/null
+++ b/speech_to_phrase/translations/en.yaml
@@ -0,0 +1,8 @@
+---
+configuration:
+ debug_logging:
+ name: Debug logging
+ description: >-
+ Enable debug logging.
+network:
+ 10300/tcp: speech-to-phrase Wyoming Protocol
diff --git a/ssh/CHANGELOG.md b/ssh/CHANGELOG.md
index 99e421186cf..4b40d6000a0 100644
--- a/ssh/CHANGELOG.md
+++ b/ssh/CHANGELOG.md
@@ -1,5 +1,72 @@
# Changelog
+## 10.0.1
+
+- Fix default shell
+
+## 10.0.0
+
+- Upgrade to Alpine 3.23
+- Upgrade Home Assistant CLI to 4.46.0
+- Use ttyd from Alpine package repository
+
+## 9.22.0
+
+- Upgrade Home Assistant CLI to 4.45.0
+
+## 9.21.0
+
+- Remove support for armhf, armv7, and i386 architectures
+- Upgrade Home Assistant CLI to 4.44.0
+
+## 9.20.1
+
+- Fix default shell
+
+## 9.20.0
+
+- Upgrade Home Assistant CLI to 4.41.0
+- Upgrade to Alpine Linux 3.22
+- Upgrade libwebsockets to 4.4.1
+
+## 9.19.0
+
+- Disable keyboard interactive authentication method if keys are used
+
+## 9.18.0
+
+- Upgrade Home Assistant CLI to 4.39.0
+
+## 9.17.0
+
+- Upgrade Home Assistant CLI to 4.38.0
+- Upgrade libwebsockets to 4.3.5
+
+## 9.16.0
+
+- Upgrade ttyd to 1.7.7 (fixes copy to clipboard using shift and drag)
+
+## 9.15.0
+
+- Upgrade Home Assistant CLI to 4.36.0
+
+## 9.14.0
+
+- Upgrade Home Assistant CLI to 4.34.0
+
+## 9.13.0
+
+- Enable ha command completion for non-login shell (e.g. the web terminal)
+
+## 9.12.0
+
+- Install completions for ha commands
+- Fix bash_history file check in startup
+
+## 9.11.0
+
+- Upgrade Home Assistant CLI to 4.32.0
+
## 9.10.0
- Upgrade Home Assistant CLI to 4.31.0
diff --git a/ssh/DOCS.md b/ssh/DOCS.md
index 894dee9f993..bd0fff551cc 100644
--- a/ssh/DOCS.md
+++ b/ssh/DOCS.md
@@ -1,25 +1,25 @@
-# Home Assistant Add-on: Terminal & SSH
+# Home Assistant App: Terminal & SSH
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. This add-on is only visible to "Advanced Mode" users. To enable advanced mode, go to **Profile** -> and turn on **Advanced Mode**.
-2. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-3. Find the "Terminal & SSH" add-on and click it.
+1. This app is only visible to "Advanced Mode" users. To enable advanced mode, go to **Profile** -> and turn on **Advanced Mode**.
+2. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+3. Find the "Terminal & SSH" app and click it.
4. Click on the "INSTALL" button.
## How to use
-This add-on adds two main features to your Home Assistant installation:
+This app adds two main features to your Home Assistant installation:
- a web terminal that you can use from your browser, and
- enable connecting to your system using an SSH client.
-Regardless of how you connect (using the web terminal or using an SSH client), you end up in this add-on's container. The Home Assistant configuration
+Regardless of how you connect (using the web terminal or using an SSH client), you end up in this app's container. The Home Assistant configuration
directory is located on the path `/config`.
-This add-on comes bundled with [The Home Assistant CLI](https://www.home-assistant.io/common-tasks/os#home-assistant-via-the-command-line). Try it out using:
+This app comes bundled with [The Home Assistant CLI](https://www.home-assistant.io/common-tasks/os#home-assistant-via-the-command-line). Try it out using:
```bash
ha help
@@ -27,7 +27,7 @@ ha help
### The Web Terminal
-You can access the web terminal by clicking the "Open Web UI" button on this add-on's Info tab. If you set the "Show in sidebar" setting (found on the same Info tab) to "on", a shortcut is added to the sidebar allowing you to access the web terminal quickly.
+You can access the web terminal by clicking the "Open Web UI" button on this app's Info tab. If you set the "Show in sidebar" setting (found on the same Info tab) to "on", a shortcut is added to the sidebar allowing you to access the web terminal quickly.
To copy text from the Web UI:
1. Hold down the SHIFT key.
@@ -39,12 +39,12 @@ To paste text into the Web UI:
### SSH Server Connection
-Remote SSH access from the network is disabled by default (See Network below). To connect using an SSH client, such as PuTTY or Linux terminal, you need to supply additional configuration for this add-on. To enable SSH connectivity, you need to:
+Remote SSH access from the network is disabled by default (See Network below). To connect using an SSH client, such as PuTTY or Linux terminal, you need to supply additional configuration for this app. To enable SSH connectivity, you need to:
- Provide authentication credentials - a password or SSH key(s)
- Specify which TCP port to bind to, on the Home Assistant host
-You can then connect to the port specified, using the username `root`. Please note that enabling the SSH Server potentially makes your Home Assistant system less secure, as it might enable anyone on the internet to try to access your system. The security of your system also depends on your network set up, router settings, use of firewalls, etc. As a general recommendation, you should not activate this part of the add-on unless you understand the ramifications.
+You can then connect to the port specified, using the username `root`. Please note that enabling the SSH Server potentially makes your Home Assistant system less secure, as it might enable anyone on the internet to try to access your system. The security of your system also depends on your network set up, router settings, use of firewalls, etc. As a general recommendation, you should not activate this part of the app unless you understand the ramifications.
If you enable connecting to the SSH Server using an SSH client, you are strongly recommended to use private/public keys to log in. As long as you keep the private part of your key safe, this makes your system much harder to break into. Using passwords is, therefore, generally considered a less secure mechanism. To generate private/public SSH keys, follow the [instructions for Windows][keygen-windows] and [these for other platforms][keygen].
@@ -54,7 +54,7 @@ Enabling login via password will disable key-based login. You can not run both v
## Configuration
-Add-on configuration:
+App configuration:
```yaml
authorized_keys:
@@ -67,7 +67,7 @@ server:
### Option: `apks`
-Additional software packages to install in the add-on container.
+Additional software packages to install in the app container.
### Option: `authorized_keys`
@@ -85,19 +85,19 @@ Some SSH server options.
#### Option `tcp_forwarding`
-Specifies whether TCP forwarding is permitted or not.
+Specifies whether TCP port forwarding (-L -R etc.) is permitted or not.
**Note**: _Enabling this option lowers the security of your SSH server! Nevertheless, this warning is debatable._
## Network
-This section is only relevant if you want to connect to Home Assistant using an SSH client, such as PuTTY or Linux terminal. To enable SSH remote access from the Network, specify the desired SSH TCP server port in the Network configuration input box. The number you enter will be used to map that port from the host into the running "Terminal & SSH" add-on. The standard port used for the SSH protocol is `22`.
+This section is only relevant if you want to connect to Home Assistant using an SSH client, such as PuTTY or Linux terminal. To enable SSH remote access from the Network, specify the desired SSH TCP server port in the Network configuration input box. The number you enter will be used to map that port from the host into the running **Terminal & SSH** app. The standard port used for the SSH protocol is `22`.
-Remote SSH access can be disabled again, by clearing the input box, saving the configuration and restarting the add-on.
+Remote SSH access can be disabled again, by clearing the input box, saving the configuration and restarting the app.
## Known issues and limitations
-- This add-on will not enable you to install packages or do anything as root.
+- This app will not enable you to install packages or do anything as root.
This is not working with Home Assistant.
## Support
@@ -116,5 +116,5 @@ In case you've found a bug, please [open an issue on our GitHub][issue].
[forum]: https://community.home-assistant.io
[issue]: https://github.com/home-assistant/addons/issues
[keygen-windows]: https://www.digitalocean.com/community/tutorials/how-to-create-ssh-keys-with-putty-to-connect-to-a-vps
-[keygen]: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/
+[keygen]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
[reddit]: https://reddit.com/r/homeassistant
diff --git a/ssh/Dockerfile b/ssh/Dockerfile
index 78c3d7b3116..9b8263c4143 100644
--- a/ssh/Dockerfile
+++ b/ssh/Dockerfile
@@ -2,10 +2,8 @@ ARG BUILD_FROM
FROM $BUILD_FROM
# Setup base
-ARG LIBWEBSOCKETS_VERSION
-ARG TTYD_VERSION
RUN \
- set -x \
+ set -x \
&& apk add --no-cache \
bash-completion \
pulseaudio-utils \
@@ -18,61 +16,16 @@ RUN \
openssh \
pwgen \
tmux \
- vim \
- \
- && apk add --no-cache --virtual .build-dependencies \
- bsd-compat-headers \
- build-base \
- linux-headers \
- cmake \
- json-c-dev \
- libuv-dev \
- openssl-dev \
- zlib-dev \
- \
- && sed -i "s/ash/bash/" /etc/passwd \
- \
- && git clone --branch "v${LIBWEBSOCKETS_VERSION}" --depth=1 \
- https://github.com/warmcat/libwebsockets.git /tmp/libwebsockets \
- \
- && mkdir -p /tmp/libwebsockets/build \
- && cd /tmp/libwebsockets/build \
- && cmake .. \
- -DCMAKE_BUILD_TYPE=MinSizeRel \
- -DCMAKE_INSTALL_PREFIX=/usr \
- -DCMAKE_VERBOSE_MAKEFILE=TRUE \
- -DLWS_IPV6=ON \
- -DLWS_STATIC_PIC=ON \
- -DLWS_UNIX_SOCK=ON \
- -DLWS_WITH_LIBUV=ON \
- -DLWS_WITH_SHARED=ON \
- -DLWS_WITHOUT_TESTAPPS=ON \
- && make \
- && make install \
- \
- && git clone --branch main --single-branch \
- https://github.com/tsl0922/ttyd.git /tmp/ttyd \
- && git -C /tmp/ttyd checkout "${TTYD_VERSION}" \
- \
- && mkdir -p /tmp/ttyd/build \
- && cd /tmp/ttyd/build \
- && cmake .. \
- -DCMAKE_BUILD_TYPE=MinSizeRel \
- -DCMAKE_INSTALL_PREFIX=/usr \
- -DCMAKE_VERBOSE_MAKEFILE=TRUE \
- && make \
- && make install \
- \
- && apk del --no-cache --purge .build-dependencies \
- && rm -f -r \
- /root/.cache \
- /root/.cmake \
- /tmp/*
+ ttyd \
+ vim
# Add YAML highlighting for nano
ADD https://raw.githubusercontent.com/scopatz/nanorc/master/yaml.nanorc /usr/share/nano/yaml.nanorc
RUN sed -i 's/^#[[:space:]]*\(include "\/usr\/share\/nano\/\*\.nanorc".*\)/\1/' /etc/nanorc
+# Use bash as default shell
+RUN sed -i "s|/bin/sh|/bin/bash|" /etc/passwd
+
# Home Assistant CLI
ARG BUILD_ARCH
ARG CLI_VERSION
diff --git a/ssh/README.md b/ssh/README.md
index 0d9d66ee637..2b286aa8f07 100644
--- a/ssh/README.md
+++ b/ssh/README.md
@@ -1,8 +1,8 @@
-# Home Assistant Add-on: SSH server
+# Home Assistant App: SSH server
Allow logging in remotely to Home Assistant using SSH or just the web terminal with Ingress.
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
## About
@@ -12,6 +12,3 @@ client. It also includes a command-line tool to access the Home Assistant API.
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
diff --git a/ssh/build.yaml b/ssh/build.yaml
index 345ed6e02a6..1eea3ffaa03 100644
--- a/ssh/build.yaml
+++ b/ssh/build.yaml
@@ -1,14 +1,6 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armhf: ghcr.io/home-assistant/armhf-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.23-2025.12.2
+ amd64: ghcr.io/home-assistant/amd64-base:3.23-2025.12.2
args:
- CLI_VERSION: 4.31.0
- LIBWEBSOCKETS_VERSION: 4.3.3
- TTYD_VERSION: 1.7.4
+ CLI_VERSION: 4.46.0
diff --git a/ssh/config.yaml b/ssh/config.yaml
index ccfefa6f04b..b8be364b6a5 100644
--- a/ssh/config.yaml
+++ b/ssh/config.yaml
@@ -1,17 +1,13 @@
---
-version: 9.10.0
+version: 10.0.1
slug: ssh
name: Terminal & SSH
description: Allow logging in remotely to Home Assistant using SSH
url: https://github.com/home-assistant/addons/tree/master/ssh
-codenotary: notary@home-assistant.io
advanced: true
arch:
- - armhf
- - armv7
- aarch64
- amd64
- - i386
audio: true
hassio_api: true
hassio_role: manager
diff --git a/ssh/rootfs/etc/cont-init.d/apks.sh b/ssh/rootfs/etc/cont-init.d/apks.sh
index 35b1d44aa31..f30f784441e 100755
--- a/ssh/rootfs/etc/cont-init.d/apks.sh
+++ b/ssh/rootfs/etc/cont-init.d/apks.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# SSH install additional packages on startup
# ==============================================================================
diff --git a/ssh/rootfs/etc/cont-init.d/keygen.sh b/ssh/rootfs/etc/cont-init.d/keygen.sh
index c913a51a8b8..6dd9efdbd57 100755
--- a/ssh/rootfs/etc/cont-init.d/keygen.sh
+++ b/ssh/rootfs/etc/cont-init.d/keygen.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# SSH Host keys
# ==============================================================================
diff --git a/ssh/rootfs/etc/cont-init.d/profile.sh b/ssh/rootfs/etc/cont-init.d/profile.sh
index dcc844b9fa8..6d4642db4eb 100755
--- a/ssh/rootfs/etc/cont-init.d/profile.sh
+++ b/ssh/rootfs/etc/cont-init.d/profile.sh
@@ -1,11 +1,12 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Setup persistent user settings
# ==============================================================================
readonly DIRECTORIES=(addon_configs addons backup homeassistant media share ssl)
# Persist shell history by redirecting .bash_history to /data
-if ! bashio::fs.file_exists /data/.bash_profile; then
+if ! bashio::fs.file_exists /data/.bash_history; then
touch /data/.bash_history
fi
chmod 600 /data/.bash_history
diff --git a/ssh/rootfs/etc/cont-init.d/ssh.sh b/ssh/rootfs/etc/cont-init.d/ssh.sh
index b008be7e8dd..4b6f2b7b29b 100755
--- a/ssh/rootfs/etc/cont-init.d/ssh.sh
+++ b/ssh/rootfs/etc/cont-init.d/ssh.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# SSH setup & user
# ==============================================================================
diff --git a/ssh/rootfs/etc/services.d/sshd/finish b/ssh/rootfs/etc/services.d/sshd/finish
index 5a23d05348c..f18f83626d1 100755
--- a/ssh/rootfs/etc/services.d/sshd/finish
+++ b/ssh/rootfs/etc/services.d/sshd/finish
@@ -1,11 +1,12 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/ssh/rootfs/etc/services.d/sshd/run b/ssh/rootfs/etc/services.d/sshd/run
index 4be0401f395..8c17525a26e 100755
--- a/ssh/rootfs/etc/services.d/sshd/run
+++ b/ssh/rootfs/etc/services.d/sshd/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start sshd service if enabled
# ==============================================================================
diff --git a/ssh/rootfs/etc/services.d/ttyd/finish b/ssh/rootfs/etc/services.d/ttyd/finish
index 5a23d05348c..f18f83626d1 100755
--- a/ssh/rootfs/etc/services.d/ttyd/finish
+++ b/ssh/rootfs/etc/services.d/ttyd/finish
@@ -1,11 +1,12 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/ssh/rootfs/etc/services.d/ttyd/run b/ssh/rootfs/etc/services.d/ttyd/run
index b3a97fe1967..4f5caad76cb 100755
--- a/ssh/rootfs/etc/services.d/ttyd/run
+++ b/ssh/rootfs/etc/services.d/ttyd/run
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start ttyd service for ingress
# ==============================================================================
diff --git a/ssh/rootfs/usr/bin/hassio b/ssh/rootfs/usr/bin/hassio
index e38eb8633a2..d96db19561b 100755
--- a/ssh/rootfs/usr/bin/hassio
+++ b/ssh/rootfs/usr/bin/hassio
@@ -1,3 +1,4 @@
#!/usr/bin/env bashio
+# vim: ft=bash
bashio::log.yellow "The 'hassio' command is deprecated, please use 'ha' instead!"
ha "$@"
diff --git a/ssh/rootfs/usr/local/bin/reboot b/ssh/rootfs/usr/local/bin/reboot
index 8ab18283c9d..15a93cd88dd 100755
--- a/ssh/rootfs/usr/local/bin/reboot
+++ b/ssh/rootfs/usr/local/bin/reboot
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# This script overrides the reboot command to reboot the host machine.
# ==============================================================================
diff --git a/ssh/rootfs/usr/local/bin/shutdown b/ssh/rootfs/usr/local/bin/shutdown
index 8dc27e3b5d7..3ab4529e2d5 100755
--- a/ssh/rootfs/usr/local/bin/shutdown
+++ b/ssh/rootfs/usr/local/bin/shutdown
@@ -1,5 +1,7 @@
-#!/usr/bin/with-contenv bashio
-# ==============================================================================
-# This script overrides the shutdown command to shutdown the host machine.
-# ==============================================================================
-bashio::host.shutdown
+#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# This script overrides the shutdown command to shutdown the host machine.
+# ==============================================================================
+bashio::host.shutdown
diff --git a/ssh/rootfs/usr/share/tempio/homeassistant.profile b/ssh/rootfs/usr/share/tempio/homeassistant.profile
index 793f4b5626b..fb3e1471ea4 100644
--- a/ssh/rootfs/usr/share/tempio/homeassistant.profile
+++ b/ssh/rootfs/usr/share/tempio/homeassistant.profile
@@ -3,3 +3,5 @@ export PS1="\[\e[0;32m\][\h \W]\$ \[\e[m\]"
export SUPERVISOR_TOKEN={{ .supervisor_token }}
ha banner
+# shellcheck disable=SC1090
+source <(ha completion bash)
diff --git a/ssh/rootfs/usr/share/tempio/sshd_config b/ssh/rootfs/usr/share/tempio/sshd_config
index 604dd7d777c..11377b240e8 100644
--- a/ssh/rootfs/usr/share/tempio/sshd_config
+++ b/ssh/rootfs/usr/share/tempio/sshd_config
@@ -19,6 +19,7 @@ PrintMotd no
{{ if .authorized_keys }}
PasswordAuthentication no
+KbdInteractiveAuthentication no
{{ else if .password }}
PasswordAuthentication yes
PermitEmptyPasswords no
diff --git a/ssh/translations/en.yaml b/ssh/translations/en.yaml
index 8157e0a9971..4f1ad3afff4 100644
--- a/ssh/translations/en.yaml
+++ b/ssh/translations/en.yaml
@@ -9,7 +9,7 @@ configuration:
apks:
name: Packages
description: >-
- Additional software packages to install in the add-on container.
+ Additional Alpine packages to install in the app container.
server:
name: Server
description: SSH Server configuration
diff --git a/tellstick/CHANGELOG.md b/tellstick/CHANGELOG.md
deleted file mode 100644
index 9be6437ccf8..00000000000
--- a/tellstick/CHANGELOG.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# Changelog
-
-## 2.2.0
-
-**Deprecation notice**
-This will be the final update for this addon. The library it depends on is abandoned.
-It's last activity was 5 years ago it it cannot be built on alpine >3.15. Users
-can continue to use it but no issues or PRs will be accepted for it going forward.
-
-- Use Alpine 3.15
-
-## 2.1.0
-
-- Update hardware configuration for Supervisor 2021.02.5
-- Use Alpine 3.13
-
-## 2.0.0
-
-- Rewrites add-on onto Bashio
-- Added documentation to the add-on repository
-- Code formatting
-
-## 1.0.0
-
-- Update base image
-
-## 0.5.0
-
-- Added possibility for config options:
- protocols: comen, fineoffset, mandolyn, oregon
- models: temperature, temperaturehumidity
-- Created changelog
diff --git a/tellstick/DOCS.md b/tellstick/DOCS.md
deleted file mode 100644
index d775d268c57..00000000000
--- a/tellstick/DOCS.md
+++ /dev/null
@@ -1,167 +0,0 @@
-# Home Assistant Add-on: TellStick
-
-## Installation
-
-Follow these steps to get the add-on installed on your system:
-
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "TellStick" add-on and click it.
-3. Click on the "INSTALL" button.
-
-## How to use
-
-### Starting the add-on
-
-After installation you are presented with a default and example configuration,
-to alter this you must follow both the JSON format and also be aligned with
-the [valid parameters for Tellstick configuration file (tellstick.conf)][conf].
-
-1. Adjust the add-on configuration to match your devices. See the add-on
- configuration options below for more details.
-2. Save the add-on configuration by clicking the "SAVE" button.
-3. Start the add-on.
-
-### Home Assistant integration
-
-You will need to add internal communication details to the `configuration.yaml`
-file to enable the integration with the add-on.
-
-```yaml
-# Example configuration.yaml entry
-tellstick:
- host: core-tellstick
- port: [50800, 50801]
-```
-
-To add lights, sensors and switches to Home Assistant, you need to follow the
-guidelines for each type individually that is described for Home Assistant.
-
-For more information, check the Home Assistant documentation:
-
-
-
-## Configuration
-
-After installation you are presented with a default and example configuration,
-to alter this you must follow both the JSON format and also be aligned with
-the [valid parameters for Tellstick configuration file (tellstick.conf)][conf].
-
-Example add-on configuration:
-
-```yaml
-devices:
- - id: 1
- name: Example device
- protocol: everflourish
- model: selflearning-switch
- house: A
- unit: '1'
- - id: 2
- name: Example device two
- protocol: everflourish
- model: selflearning-switch
- house: A
- unit: '2'
-```
-
-Please note: After any changes have been made to the configuration,
-you need to restart the add-on for the changes to take effect.
-
-### Option: `devices` (required)
-
-Add one or more devices entries to the add-on configuration for each
-device you'd like to add. Please note the comma separator between each
-device (see example above).
-
-#### Option: `devices.id` (required)
-
-A unique number / identifier that must be unique for each device.
-
-#### Option: `devices.name` (required)
-
-A name for your device, making it easier to identify it.
-
-#### Option: `devices.protocol` (required)
-
-This is the protocol the device uses. For a full list of supported protocols
-(and thus valid values for this configuration option), check the
-TellStick [protocol list][protocol-list].
-
-#### Option: `devices.model` (optional)
-
-The model parameter is only used by some protocols where there exists different
-types of devices using the same protocol. This can be dimmers versus non-dimmers,
-codeswitch versus self-learning, etc.
-
-#### Option: `devices.house` (optional)
-
-Depending on protocol the values here can vary a lot to identify
-or group per house or type.
-
-#### Option: `devices.unit` (optional)
-
-Unit identifier, in most cases a value between 1 to 16 and often used in
-combination with the house.
-
-#### Option: `devices.fade` (optional)
-
-Fade is either `true` or `false` and tells a dimmer if it should fade smooth
-or instant between values (only for IKEA protocol as it seems).
-
-#### Option: `devices.code` (optional)
-
-A number series based on ones and zeroes often used for dip-switch based devices.
-
-## Service calls
-
-If you wish to teach a self-learning device in your TellStick configuration:
-
-Go to Home Assistant service call in Developer tools and select:
-
-- Service: `hassio.addon_stdin`
-- Enter service Data:
- `{"addon":"core_tellstick","input":{"function":"learn","device":"1"}}`
-
-Replace `1` with the corresponding ID of the device in your TellStick configuration.
-
-You can also use this to list devices or sensors and read the output in the
-add-on log: `{"addon":"core_tellstick","input":{"function":"list-sensors"}}`
-
-### Supported service commands
-
-- `"function":"list"`
- List currently configured devices with name and device id and all discovered sensors.
-
-- `"function":"list-sensors"`
-
-- `"function":"list-devices"`
- Alternative devices/sensors listing: Shows devices and/or sensors using key=value
- format (with tabs as separators, one device/sensor per line, no header lines.)
-
-- `"function":"on","device":"x"`
- Turns on device. ’x’ could either be an integer of the device-id,
- or the name of the device.
-
-- `"function":"off","device":"x"`
- Turns off device. ’x’ could either be an integer of the device-id,
- or the name of the device.
-
-## Support
-
-Got questions?
-
-You have several options to get them answered:
-
-- The [Home Assistant Discord Chat Server][discord].
-- The Home Assistant [Community Forum][forum].
-- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]
-
-In case you've found a bug, please [open an issue on our GitHub][issue].
-
-[conf]: http://developer.telldus.com/wiki/TellStick_conf
-[discord]: https://discord.gg/c5DvZ4e
-[forum]: https://community.home-assistant.io
-[issue]: https://github.com/home-assistant/addons/issues
-[protocol-list]: http://developer.telldus.com/wiki/TellStick_conf
-[reddit]: https://reddit.com/r/homeassistant
-[repository]: https://github.com/hassio-addons/repository
diff --git a/tellstick/Dockerfile b/tellstick/Dockerfile
deleted file mode 100644
index ced11dab864..00000000000
--- a/tellstick/Dockerfile
+++ /dev/null
@@ -1,48 +0,0 @@
-ARG BUILD_FROM
-FROM $BUILD_FROM
-
-ENV LANG C.UTF-8
-
-# Install Telldus library for TellStick (using same approach as in hassio docker installation)
-ARG TELLDUS_COMMIT
-RUN \
- set -x \
- && apk add --no-cache \
- confuse \
- libftdi1 \
- libstdc++ \
- socat \
- && apk add --no-cache --virtual .build-dependencies \
- argp-standalone \
- build-base \
- cmake \
- confuse-dev \
- doxygen \
- gcc \
- git \
- libftdi1-dev \
- && ln -s /usr/include/libftdi1/ftdi.h /usr/include/ftdi.h \
- && mkdir -p /usr/src \
- && cd /usr/src \
- && git clone https://github.com/telldus/telldus \
- && cd telldus/telldus-core \
- && git reset --hard ${TELLDUS_COMMIT} \
- && sed -i \
- "/\/a \#include \" \
- common/Socket_unix.cpp \
- && cmake . \
- -DBUILD_LIBTELLDUS-CORE=ON \
- -DBUILD_TDADMIN=OFF \
- -DBUILD_TDTOOL=ON \
- -DGENERATE_MAN=OFF \
- -DFORCE_COMPILE_FROM_TRUNK=ON \
- -DFTDI_LIBRARY=/usr/lib/libftdi1.so \
- && make \
- && make install \
- && apk del .build-dependencies \
- && rm -rf /usr/src/telldus
-
-# Copy data for add-on
-COPY data/run.sh /
-
-CMD [ "/run.sh" ]
diff --git a/tellstick/README.md b/tellstick/README.md
deleted file mode 100644
index 24b498b2bf3..00000000000
--- a/tellstick/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Home Assistant Add-on: TellStick
-
-TellStick and TellStick Duo service.
-
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
-
-## About
-
-This add-on wraps around the `telldus-core` package to expose a service
-for your TellStick and TellStick Duo.
-
-This integration allows users to add switches, lights, and sensors which are
-communicating with 433 MHz. There are a number of vendors (Capidi Elro,
-Intertechno, Nexa, Proove, Sartano, and Viking) who are selling products that
-work with TellStick.
-
-For more details, please check the TellStick [protocol list][protocol-list].
-
-
-[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
-[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
\ No newline at end of file
diff --git a/tellstick/build.yaml b/tellstick/build.yaml
deleted file mode 100644
index fb0bee1d4e1..00000000000
--- a/tellstick/build.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.15
- amd64: ghcr.io/home-assistant/amd64-base:3.15
- armhf: ghcr.io/home-assistant/armhf-base:3.15
- armv7: ghcr.io/home-assistant/armv7-base:3.15
- i386: ghcr.io/home-assistant/i386-base:3.15
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
-args:
- TELLDUS_COMMIT: 2598bbed16ffd701f2a07c99582f057a3decbaf3
diff --git a/tellstick/config.yaml b/tellstick/config.yaml
deleted file mode 100644
index 053a820d696..00000000000
--- a/tellstick/config.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
----
-version: 2.2.0
-slug: tellstick
-name: TellStick
-description: TellStick and TellStick Duo service
-url: https://github.com/home-assistant/addons/tree/master/tellstick
-arch:
- - armhf
- - armv7
- - aarch64
- - amd64
- - i386
-image: homeassistant/{arch}-addon-tellstick
-options:
- devices:
- - house: A
- id: 1
- model: selflearning-switch
- name: Example device
- protocol: everflourish
- unit: "1"
- - house: A
- id: 2
- model: selflearning-switch
- name: Example device two
- protocol: everflourish
- unit: "2"
-schema:
- devices:
- - code: str?
- fade: str?
- house: str?
- id: int(1,)
- model: "match(codeswitch|bell|selflearning-switch|selflearning-dimmer|\
- selflearning|ecosavers|kp100|temperaturehumidity|temperature)?"
- name: str
- protocol: "match(arctech|brateck|comen|everflourish|fineoffset|fuhaote|\
- hasta|ikea|kangtai|mandolyn|oregon|risingsun|sartano|\
- silvanchip|upm|waveman|x10|yidong)"
- unit: str?
-startup: system
-stdin: true
-usb: true
-init: false
-stage: deprecated
diff --git a/tellstick/data/run.sh b/tellstick/data/run.sh
deleted file mode 100755
index 1b57bf3f96d..00000000000
--- a/tellstick/data/run.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/with-contenv bashio
-set -e
-
-CONFIG="/etc/tellstick.conf"
-
-bashio::log.info "Initialize the tellstick configuration..."
-# User access
-{
- echo "user = \"root\""
- echo "group = \"plugdev\""
- echo "ignoreControllerConfirmation = \"false\""
-} > "${CONFIG}"
-
-# devices
-for device in $(bashio::config 'devices|keys'); do
- DEV_ID=$(bashio::config "devices[${device}].id")
- DEV_NAME=$(bashio::config "devices[${device}].name")
- DEV_PROTO=$(bashio::config "devices[${device}].protocol")
- DEV_MODEL=$(bashio::config "devices[${device}].model")
- ATTR_HOUSE=$(bashio::config "devices[${device}].house")
- ATTR_CODE=$(bashio::config "devices[${device}].code")
- ATTR_UNIT=$(bashio::config "devices[${device}].unit")
- ATTR_FADE=$(bashio::config "devices[${device}].fade")
-
- (
- echo ""
- echo "device {"
- echo " id = ${DEV_ID}"
- echo " name = \"${DEV_NAME}\""
- echo " protocol = \"${DEV_PROTO}\""
-
- bashio::var.has_value "${DEV_MODEL}" \
- && echo " model = \"${DEV_MODEL}\""
-
- if bashio::var.has_value "${ATTR_HOUSE}${ATTR_CODE}${ATTR_UNIT}${ATTR_FADE}";
- then
- echo " parameters {"
-
- bashio::var.has_value "${ATTR_HOUSE}" \
- && echo " house = \"${ATTR_HOUSE}\""
-
- bashio::var.has_value "${ATTR_CODE}" \
- && echo " code = \"${ATTR_CODE}\""
-
- bashio::var.has_value "${ATTR_UNIT}" \
- && echo " unit = \"${ATTR_UNIT}\""
-
- bashio::var.has_value "${ATTR_FADE}" \
- && echo " fade = \"${ATTR_FADE}\""
-
- echo " }"
- fi
-
- echo "}"
- ) >> "${CONFIG}"
-done
-
-bashio::log.info "Exposing sockets and loading service..."
-
-# Expose the unix socket to internal network
-socat TCP-LISTEN:50800,reuseaddr,fork UNIX-CONNECT:/tmp/TelldusClient &
-socat TCP-LISTEN:50801,reuseaddr,fork UNIX-CONNECT:/tmp/TelldusEvents &
-
-# Run telldus-core daemon in the background
-/usr/local/sbin/telldusd --nodaemon < /dev/null &
-
-# Listen for input to tdtool
-bashio::log.info "Starting event listener..."
-while read -r input; do
- # parse JSON value
- funct=$(bashio::jq "${input}" '.function')
- devid=$(bashio::jq "${input}" '.device // empty')
- bashio::log.info "Read ${funct} / ${devid}"
-
- if ! msg="$(tdtool "--${funct}" "${devid}")"; then
- bashio::log.error "TellStick ${funct} fails -> ${msg}"
- else
- bashio::log.info "TellStick ${funct} success -> ${msg}"
- fi
-done
diff --git a/tellstick/icon.png b/tellstick/icon.png
deleted file mode 100644
index 1b40bd9b124..00000000000
Binary files a/tellstick/icon.png and /dev/null differ
diff --git a/tellstick/logo.png b/tellstick/logo.png
deleted file mode 100644
index 82a92e94f80..00000000000
Binary files a/tellstick/logo.png and /dev/null differ
diff --git a/tellstick/translations/en.yaml b/tellstick/translations/en.yaml
deleted file mode 100644
index 22b08727503..00000000000
--- a/tellstick/translations/en.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-configuration:
- devices:
- name: Devices
- description: >-
- Add one or more devices entries to the add-on configuration for each
- device you'd like to add.
diff --git a/vlc/CHANGELOG.md b/vlc/CHANGELOG.md
index b505485fa3d..3c9cb387b26 100644
--- a/vlc/CHANGELOG.md
+++ b/vlc/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 0.3.1
+
+- Restart VLC on Audio plug-in restart
+- Update to Alpine 3.22
+
## 0.3.0
- Prevent race condition reading secrets on startup
diff --git a/vlc/DOCS.md b/vlc/DOCS.md
index 0af36af75e5..feb528d382d 100644
--- a/vlc/DOCS.md
+++ b/vlc/DOCS.md
@@ -1,23 +1,23 @@
-# Home Assistant Add-on: VLC
+# Home Assistant App: VLC
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app (formerly known as add-on) installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "VLC" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "VLC" app and click it.
3. Click on the "INSTALL" button.
## How to use
-1. Start the add-on.
+1. Start the app.
2. Add the VLC Telnet integration to Home Assistant, see documentation:
## Configuration
-Note that automatic discovery is expected when the add-on is being installed. If no "VLC media player via Telnet" integration is being discovered, make sure to remove any stale "VLC media player via Telnet" integrations and reinstall the add-on to trigger discovery again.
+Note that automatic discovery is expected when the app is being installed. If no "VLC media player via Telnet" integration is being discovered, make sure to remove any stale "VLC media player via Telnet" integrations and reinstall the app to trigger discovery again.
## Support
diff --git a/vlc/Dockerfile b/vlc/Dockerfile
index 048f2269563..21ab5499d4f 100644
--- a/vlc/Dockerfile
+++ b/vlc/Dockerfile
@@ -6,6 +6,7 @@ WORKDIR /usr/src
RUN \
set -x \
&& apk add --no-cache \
+ inotify-tools \
nginx \
pwgen \
vlc \
diff --git a/vlc/README.md b/vlc/README.md
index eec7809e845..0cb746bc5f0 100644
--- a/vlc/README.md
+++ b/vlc/README.md
@@ -1,4 +1,4 @@
-# Home Assistant Add-on: VLC
+# Home Assistant App: VLC
Allow Home Assistant to use your local device as Media Player.
diff --git a/vlc/build.yaml b/vlc/build.yaml
index ecb8cacf60b..7b748a43247 100644
--- a/vlc/build.yaml
+++ b/vlc/build.yaml
@@ -1,9 +1,6 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.19
- amd64: ghcr.io/home-assistant/amd64-base:3.19
- armv7: ghcr.io/home-assistant/armv7-base:3.19
- i386: ghcr.io/home-assistant/i386-base:3.19
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.22
+ amd64: ghcr.io/home-assistant/amd64-base:3.22
+ armv7: ghcr.io/home-assistant/armv7-base:3.22
+ i386: ghcr.io/home-assistant/i386-base:3.22
diff --git a/vlc/config.yaml b/vlc/config.yaml
index 92364b428f2..381cbb8d7d1 100644
--- a/vlc/config.yaml
+++ b/vlc/config.yaml
@@ -1,5 +1,5 @@
---
-version: 0.3.0
+version: 0.3.1
slug: vlc
name: VLC
description: Turn your device into a Media Player with VLC
diff --git a/vlc/rootfs/etc/cont-init.d/ingress.sh b/vlc/rootfs/etc/cont-init.d/ingress.sh
index e3e17951481..1a40e83ff0d 100755
--- a/vlc/rootfs/etc/cont-init.d/ingress.sh
+++ b/vlc/rootfs/etc/cont-init.d/ingress.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Prepare VLC for ingress access
# ==============================================================================
diff --git a/vlc/rootfs/etc/cont-init.d/secret.sh b/vlc/rootfs/etc/cont-init.d/secret.sh
index e44da81a8fb..c690bc8cc9d 100755
--- a/vlc/rootfs/etc/cont-init.d/secret.sh
+++ b/vlc/rootfs/etc/cont-init.d/secret.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Create VLC secret
# ==============================================================================
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
index 68ccc43357e..8d30b99a18d 100755
--- a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
@@ -6,7 +7,7 @@
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
index f4fad4cbe88..28b0ae417aa 100755
--- a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start NGINX service
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/dependencies.d/base b/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/dependencies.d/base
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/run b/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/run
new file mode 100755
index 00000000000..714f2a1f097
--- /dev/null
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/run
@@ -0,0 +1,29 @@
+#!/command/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
+# ==============================================================================
+# PulseAudio socket monitor service
+# ==============================================================================
+
+bashio::log.info "Starting PulseAudio socket monitor..."
+
+while true; do
+ if [ -S "/run/audio/pulse.sock" ]; then
+ bashio::log.debug "Monitoring /run/audio/pulse.sock for changes..."
+ if ! inotifywait -q -e delete_self "/run/audio/pulse.sock"; then
+ bashio::log.warning "inotifywait failed, retrying in 5 seconds..."
+ sleep 5
+ continue
+ fi
+
+ bashio::log.info "PulseAudio socket deleted, restarting VLC service..."
+ s6-rc -d change vlc
+ sleep 1
+ s6-rc -u change vlc
+
+ bashio::log.info "VLC service restarted"
+ else
+ bashio::log.debug "PulseAudio socket not found, waiting 5 seconds..."
+ sleep 5
+ fi
+done
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/type b/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/type
new file mode 100644
index 00000000000..1780f9f44ef
--- /dev/null
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/pulse-monitor/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/pulse-monitor b/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/pulse-monitor
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish
index 68ccc43357e..8d30b99a18d 100755
--- a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
@@ -6,7 +7,7 @@
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run
index 27617f08381..41dff72bc92 100755
--- a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run
+++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run
@@ -1,10 +1,21 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start VLC service
# ==============================================================================
+# shellcheck disable=SC2155
readonly PASSWORD="$(cat /data/secret)"
+bashio::log.info "Waiting for PulseAudio socket to become available..."
+
+while [ ! -S "/run/audio/pulse.sock" ]
+do
+ sleep 1
+done
+
+bashio::log.info "PulseAudio socket available, starting VLC"
+
# Send out discovery information to Home Assistant
/etc/s6-overlay/scripts/vlc-discovery &
diff --git a/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery b/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery
index f140d8b075c..70910304477 100755
--- a/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery
+++ b/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Send vlc_telnet discovery information to Home Assistant
# ==============================================================================
diff --git a/whisper/CHANGELOG.md b/whisper/CHANGELOG.md
index 61f71b1fb59..a32f02aaff7 100644
--- a/whisper/CHANGELOG.md
+++ b/whisper/CHANGELOG.md
@@ -1,5 +1,57 @@
# Changelog
+## 3.1.0
+
+- Fix model selection for language
+- Prefer Parakeet only for English (detection fails for other languages)
+- Add missing `onnx_asr` dependency
+
+## 3.0.1
+
+- Add support for `sherpa-onnx` and Nvidia's parakeet model
+- Prefer parakeet model in `auto`
+- Add support for GigaAM for Russian
+- Add `stt_library` option to choose backend
+
+## 2.6.0
+
+- Upgrade to Debian bookworm
+- Add support for HuggingFace transformers Whisper models
+
+## 2.5.0
+
+- Added configuration mapping to access local models.
+- Updated documentation about `custom_model` usage.
+
+## 2.4.0
+
+- Add "auto" for model and beam size (0) to select values based on CPU
+
+## 2.3.1
+
+- Move `turbo` down the list closer to `large` to avoid confusion
+
+## 2.3.0
+
+- Bump `wyoming-whisper` to 2.3.0 (`faster-whisper` to 1.1.0)
+- Supports model `turbo` for faster processing
+
+## 2.2.0
+
+- Bump `wyoming-whisper` to 2.2.0 (`faster-whisper` to 1.0.3)
+
+## 2.1.2
+
+- Fix excluding models files from backup
+
+## 2.1.1
+
+- Exclude `data/models*` files from backup
+
+## 2.1.0
+
+- Add distil-large-v3 `model` option
+
## 2.0.0
- Add more models for `model` option
diff --git a/whisper/DOCS.md b/whisper/DOCS.md
index a839cf2b153..e9de237c223 100644
--- a/whisper/DOCS.md
+++ b/whisper/DOCS.md
@@ -1,16 +1,16 @@
-# Home Assistant Add-on: Whisper
+# Home Assistant App: Whisper
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**.
-2. Find the "Whisper" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Whisper" app and click it.
3. Click on the "INSTALL" button.
## How to use
-After this add-on is installed and running, it will be automatically discovered
+After this app is installed and running, it will be automatically discovered
by the Wyoming integration in Home Assistant. To finish the setup,
click the following my button:
@@ -24,7 +24,7 @@ for more information.
### Option: `language`
-Default language for the add-on. In Home Assist 2023.8+, multiple languages can be used simultaneously by different [Assist pipelines](https://www.home-assistant.io/voice_control/voice_remote_local_assistant/).
+Default language for the app. In Home Assist 2023.8+, multiple languages can be used simultaneously by different [Assist pipelines](https://www.home-assistant.io/voice_control/voice_remote_local_assistant/).
If you select "auto", the model will run **much** slower but will auto-detect the spoken language.
@@ -36,11 +36,12 @@ If you select "auto", the model will run **much** slower but will auto-detect th
Whisper model that will be used for transcription. Choose `custom` to use the model name in `custom_model`, which may be a HuggingFace model ID like "Systran/faster-distil-whisper-small.en".
-The default model is `tiny-int8`, a compressed version of the smallest Whisper model which is able to run on a Raspberry Pi 4.
+The default model is `auto`, which selects `tiny-int8` for ARM devices like the Raspberry Pi 4 and `base-int8` otherwise.
Compressed models (`int8`) are slightly less accurate than their counterparts, but smaller and faster. [Distilled](https://github.com/huggingface/distil-whisper) models are not compressed, but are faster and smaller than their non-distilled counterparts.
Available models:
+- `auto` (select based on CPU)
- `tiny-int8` (compressed)
- `tiny`
- `tiny.en` (English only)
@@ -59,15 +60,34 @@ Available models:
- `large-v1`
- `distil-large-v2` (distilled, English only)
- `large-v2`
+- `distil-large-v3` (distilled, English only)
- `large-v3`
+- `turbo` (faster than `large-v3`)
### Option: `custom_model`
-Path to a converted model directory, or a CTranslate2-converted Whisper model ID from the HuggingFace Hub like "Systran/faster-distil-whisper-small.en".
+Path to a converted model directory, or a CTranslate2-converted Whisper model ID from the HuggingFace Hub like "Systran/faster-distil-whisper-small.en".
+
+If `custom_model_type` is set to `transformers`, a HuggingFace transformers Whisper model ID from HuggingFace like "openai/whisper-tiny.en" must be used.
+
+To use a local custom Whisper model, first create a `models` subdirectory in the app's configuration directory if it does not already exist. Then copy your model directory into:
+`/addon_configs/core_whisper/models/`.
+Then, set the `custom_model` path to:
+`/config/models/`. For a local model, the path must start with `/config/models/`, as this is how the add-on accesses your Home Assistant configuration directory through the container's mounted volume.
+
+### Option: `custom_model_type`
+
+Either `faster-whisper` (the default) or `transformers`.
+
+When set to `transformers`, the `custom_model` option must be a HuggingFace transformers-based Whisper model like "openai/whisper-tiny.en".
+
+**Note:** Initial prompt is currently not supported for transformers-based models.
+
### Option: `beam_size`
Number of candidates to consider simultaneously during transcription (see [beam search](https://en.wikipedia.org/wiki/Beam_search)).
+The default value of `0` will automatically select `1` of ARM devices like the Raspberry Pi 4 and `5` otherwise.
Increasing the beam size will increase accuracy at the cost of performance.
@@ -76,9 +96,21 @@ Increasing the beam size will increase accuracy at the cost of performance.
Description of audio that can help Whisper transcribe unusual words better.
See [this discussion](https://github.com/openai/whisper/discussions/963) for an example.
+### Option: `stt_library`
+
+Speech-to-text backend library to use:
+
+- `auto` - select the best backend based on language/hardware
+- `faster-whisper` - force faster whisper backend
+- `sherpa` - force sherpa onnx backend (parakeet model only)
+- `transformers` - force HuggingFace transformers backend
+
+**Note**: When `custom_model` is set, then `custom_model_type` will override `stt_library`.
+
## Backups
-Whisper model files can be quite large, so they are automatically excluded from backups. The models will be re-downloaded when the backup is restored.
+Whisper model files can be large, so they are automatically excluded from backups and re-downloaded on restore for remote models.
+After restoring a backup with a local custom Whisper model, manually copy your model directory again.
## Support
diff --git a/whisper/Dockerfile b/whisper/Dockerfile
index eeecbda4a92..2b65dd91bcf 100644
--- a/whisper/Dockerfile
+++ b/whisper/Dockerfile
@@ -4,12 +4,13 @@ FROM ${BUILD_FROM}
# Install Whisper
WORKDIR /usr/src
ARG WYOMING_WHISPER_VERSION
+ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN \
apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
- netcat \
+ netcat-traditional \
python3 \
python3-dev \
python3-pip \
@@ -18,7 +19,14 @@ RUN \
setuptools \
wheel \
&& pip3 install --no-cache-dir \
- "wyoming-faster-whisper @ https://github.com/rhasspy/wyoming-faster-whisper/archive/refs/tags/v${WYOMING_WHISPER_VERSION}.tar.gz" \
+ "wyoming[zeroconf]==1.8.0" \
+ "wyoming-faster-whisper[sherpa] @ https://github.com/rhasspy/wyoming-faster-whisper/archive/refs/tags/v${WYOMING_WHISPER_VERSION}.tar.gz" \
+ 'transformers==4.52.4' \
+ 'onnx-asr[cpu,hub]==0.7.0' \
+ \
+ && pip3 install --no-cache-dir \
+ --index-url 'https://download.pytorch.org/whl/cpu' \
+ 'torch==2.6.0' \
\
&& apt-get purge -y --auto-remove \
build-essential \
diff --git a/whisper/README.md b/whisper/README.md
index 75d92c987e9..0c766203c3a 100644
--- a/whisper/README.md
+++ b/whisper/README.md
@@ -1,13 +1,15 @@
-# Home Assistant Add-on: Whisper
+# Home Assistant App: Whisper
![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
-Home Assistant add-on that uses [faster-whisper](https://github.com/guillaumekln/faster-whisper/) for speech-to-text.
+Home Assistant app (formerly known as add-on) that uses multiple speech-to-text backends:
+
+- [faster-whisper](https://github.com/guillaumekln/faster-whisper/)
+- [HuggingFace transformers](https://huggingface.co/docs/transformers/index)
+- [sherpa-onnx](https://k2-fsa.github.io/sherpa/onnx/index.html) ([parakeet](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) only)
+- [onnx-asr](https://github.com/istupakov/onnx-asr) ([GigaAM](https://github.com/salute-developers/GigaAM) only)
Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/).
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg
-[i386-shield]: https://img.shields.io/badge/i386-no-red.svg
diff --git a/whisper/build.yaml b/whisper/build.yaml
index abe0b9f8895..eda3ebe7922 100644
--- a/whisper/build.yaml
+++ b/whisper/build.yaml
@@ -1,9 +1,6 @@
---
build_from:
- amd64: ghcr.io/home-assistant/amd64-base-debian:bullseye
- aarch64: ghcr.io/home-assistant/aarch64-base-debian:bullseye
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm
+ aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm
args:
- WYOMING_WHISPER_VERSION: 2.1.0
+ WYOMING_WHISPER_VERSION: 3.1.0
diff --git a/whisper/config.yaml b/whisper/config.yaml
index 4cf77c866b1..6fddd8ed406 100644
--- a/whisper/config.yaml
+++ b/whisper/config.yaml
@@ -1,5 +1,5 @@
---
-version: 2.0.0
+version: 3.1.0
slug: whisper
name: Whisper
description: Speech-to-text with Whisper
@@ -11,16 +11,24 @@ init: false
discovery:
- wyoming
backup_exclude:
- - "*.bin"
+ - "models*"
+map:
+ - addon_config:rw
options:
- model: tiny-int8
+ model: auto
language: en
- beam_size: 1
+ beam_size: 0
+ custom_model_type: "faster-whisper"
+ stt_library: "auto"
debug_logging: false
schema:
model: |
- list(tiny-int8|tiny|tiny.en|base-int8|base|base.en|small-int8|distil-small.en|small|small.en|distil-medium.en|medium-int8|medium|medium.en|large|large-v1|distil-large-v2|large-v2|large-v3|custom)
+ list(auto|tiny-int8|tiny|tiny.en|base-int8|base|base.en|small-int8|distil-small.en|small|small.en|distil-medium.en|medium-int8|medium|medium.en|large|large-v1|distil-large-v2|large-v2|distil-large-v3|large-v3|turbo|custom)
+ stt_library: |
+ list(auto|faster-whisper|sherpa|transformers)
custom_model: str?
+ custom_model_type: |
+ list(faster-whisper|transformers)
language: |
list(auto|af|am|ar|as|az|ba|be|bg|bn|bo|br|bs|ca|cs|cy|da|de|el|en|es|et|eu|fa|fi|fo|fr|gl|gu|ha|haw|he|hi|hr|ht|hu|hy|id|is|it|ja|jw|ka|kk|km|kn|ko|la|lb|ln|lo|lt|lv|mg|mi|mk|ml|mn|mr|ms|mt|my|ne|nl|nn|no|oc|pa|pl|ps|pt|ro|ru|sa|sd|si|sk|sl|sn|so|sq|sr|su|sv|sw|ta|te|tg|th|tk|tl|tr|tt|uk|ur|uz|vi|yi|yo|zh|yue)
beam_size: int
diff --git a/whisper/icon.png b/whisper/icon.png
index 410fbc409e9..a9bdb11ad5b 100644
Binary files a/whisper/icon.png and b/whisper/icon.png differ
diff --git a/whisper/logo.png b/whisper/logo.png
index 33113ee52c1..ed85b39c88d 100644
Binary files a/whisper/logo.png and b/whisper/logo.png differ
diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
index db71276aee7..979e7a58ab0 100755
--- a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
+++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run
@@ -1,4 +1,5 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Sends discovery information to Home Assistant.
diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish
index 15e4760e475..0bc8d2e7ab5 100755
--- a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish
+++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish
@@ -1,10 +1,11 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
-declare exit_code
+# shellcheck disable=SC2155
readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode
+ echo $((128 + exit_code_signal)) > /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
diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run
index efe2ca2e1c1..5df6c174090 100755
--- a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run
+++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run
@@ -1,19 +1,29 @@
#!/command/with-contenv bashio
+# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Start Whisper service
# ==============================================================================
+flags=()
if [ "$(uname -m)" == "x86_64" ] && ! grep -qw 'avx' /proc/cpuinfo; then
bashio::log.warning "Your CPU does not support Advanced Vector Extensions (AVX). Whisper will run slower than normal."
fi
model="$(bashio::config 'model')"
+stt_library="$(bashio::config 'stt_library')"
+
if [ "${model}" = 'custom' ]; then
# Override with custom model
model="$(bashio::config 'custom_model')"
if [ -z "${model}" ]; then
- bashio::exit.nok "Custom model is not set"
+ bashio::exit.nok "Custom model is not set"
+ fi
+ stt_library="$(bashio::config 'custom_model_type')"
+elif [ "${model}" != 'auto' ]; then
+ if [ "${stt_library}" = 'auto' ]; then
+ # Default to faster whisper if model is selected
+ stt_library='faster-whisper'
fi
fi
@@ -21,9 +31,12 @@ if bashio::config.true 'debug_logging'; then
flags+=('--debug')
fi
+# shellcheck disable=SC2068
exec python3 -m wyoming_faster_whisper \
--uri 'tcp://0.0.0.0:10300' \
+ --zeroconf \
--model "${model}" \
+ --stt-library "${stt_library}" \
--beam-size "$(bashio::config 'beam_size')" \
--language "$(bashio::config 'language')" \
--initial-prompt "$(bashio::config 'initial_prompt')" \
diff --git a/whisper/translations/en.yaml b/whisper/translations/en.yaml
index 3e0c1b5aad4..4011ca8d216 100644
--- a/whisper/translations/en.yaml
+++ b/whisper/translations/en.yaml
@@ -3,18 +3,17 @@ configuration:
beam_size:
name: Beam size
description: >-
- Number of candidates to consider simultaneously during transcription.
- Increasing the beam size will increase accuracy at the cost of
+ Number of candidates to consider simultaneously during transcription (0 =
+ auto). Increasing the beam size will increase accuracy at the cost of
performance.
language:
name: Language
description: >-
- Language that you will speak to the add-on. If you select "auto",
- the model will run much slower but will auto-detect the spoken language.
+ Language to pre-load model for during start-up.
model:
name: Model
description: |
- Whisper model that will be used for transcription.
+ Whisper model that will be used for transcription (faster-whisper only).
The default model is `tiny-int8`, a compressed version of the smallest
Whisper model which is able to run on a Raspberry Pi 4. Compressed models
@@ -26,14 +25,37 @@ configuration:
Path to a converted model directory, or a CTranslate2-converted Whisper
model ID from the HuggingFace Hub like
"Systran/faster-distil-whisper-small.en".
+
+ If custom_model_type is set to 'transformers', a HuggingFace transformers
+ Whisper model ID from HuggingFace like 'openai/whisper-tiny.en' may be
+ used.
+ custom_model_type:
+ name: Custom model type
+ description: |
+ Type of Whisper model expected from custom model.
+
+ The default is 'faster-whisper' which requires a CTranslate2-converted
+ Whisper model. If set to 'transformers', a HuggingFace transformers-based
+ Whisper model may be used.
+
+ Overrides `stt_library` when `custom_model` is set.
initial_prompt:
name: Initial prompt
description: >-
Description of audio that can help Whisper transcribe unusual words
better.
+ stt_library:
+ name: Speech-to-text library
+ description: >-
+ Speech-to-text backend library to use.
+
+ The default `auto` will select the best backend/model based on
+ language/hardware.
+
+ Overridden by `custom_model_type` when `custom_model` is set.
debug_logging:
name: Debug logging
description: >-
- Print DEBUG level messages to the add-on's log.
+ Print DEBUG level messages to the app's log.
network:
10300/tcp: Whisper Wyoming Protocol
diff --git a/zwave_js/CHANGELOG.md b/zwave_js/CHANGELOG.md
index 37e49bde49a..5646fd155fd 100644
--- a/zwave_js/CHANGELOG.md
+++ b/zwave_js/CHANGELOG.md
@@ -1,5 +1,963 @@
# Changelog
+## 1.0.0
+
+**NOTE: It is strongly recommended to make a backup before updating to this version.**
+
+This release includes [Z-Wave JS UI](https://github.com/zwave-js/zwave-js-ui) as an optional management UI to support advanced use-cases.
+
+### Breaking changes
+
+- Version 1.0.0 of the add-on requires version 2025.12.0 or higher of Home Assistant Core.
+- Drop support for armhf, armv7 and i386 architectures
+- Remove `emulate_hardware` configuration option
+
+### Other changes
+
+- Update base image to Alpine 3.23
+
+## 0.29.1
+
+### Z-Wave JS 15.20.1
+
+#### Bugfixes
+
+- Clean up unnecessary "device config changed" repairs that could appear after updating to Z-Wave JS 15.20.0 / addon version 0.29.0 without skipping Z-Wave JS 15.20.0 / addon version 0.28.0.
+
+#### Config file changes
+
+- Add Zooz Zen57 240V XS Relay
+- Add MCO Home MH-5900 thermostat
+- Update Zooz ZEN35 configuration for firmware 1.10 and later
+- Update Zooz ZEN14 configuration for firmware 2.20
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.20.0...15.20.1](https://github.com/zwave-js/zwave-js/compare/v15.20.0...v15.20.1)
+
+## 0.29.0
+
+### Z-Wave JS 15.20.0
+
+#### Features
+
+- Sound Switch CC: Reset the current tone back to none when done playing
+- Support connecting to ESPHome Z-Wave proxies with API encryption
+- Try to find Z-Wave QR code strings in longer strings
+
+#### Bugfixes
+
+- Avoid false positive detections for changed device configs after upgrading from a version before 15.19.0
+
+#### Config file changes
+
+- Update Zooz ZEN16 to support 800 series version
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.19.0...15.20.0](https://github.com/zwave-js/zwave-js/compare/v15.19.0...v15.20.0)
+
+## 0.28.0
+
+### Z-Wave JS 15.19.0
+
+#### Features
+
+- Add option to force associations without checking if they are valid/allowed
+- Devices that failed to include with Security S2 are no longer interviewed
+
+#### Bugfixes
+
+- During the initial interview after inclusion, user codes are now cleared unless `queryAllUserCodes` driver option is set
+- The `ConfigurationCCDefaultReset` command now uses Supervision if supported
+- Correct log messages for `SoundSwitchCCConfigurationSet`
+- Fixed an issue where `setValue` calls with `disableOptimisticValueUpdate` would cause the next `value updated` event to have an incorrect previous value
+- Fixed an issue where some 500 series controllers could hang during an NVM backup
+
+#### Config file changes
+
+- Add missing parameter for latest VZW31-SN firmware
+- Correct manual link metadata for Inovelli VZW31-SN and VZW32-SN
+- Label endpoints of Shelly Wave Shutter
+- Remove unnecessary firmware version check from Zooz ZEN35
+- Add fingerprint for Kwikset HC620
+- Add Zooz Zen58 Low Voltage XS Relay
+- Hide VZW32-SN test parameter from production use
+- Add Aeotec ZWA050 SmokeShield for Ei Smoke Detectors
+
+### Z-Wave JS 15.18.0
+
+#### Features
+
+- Device configuration parameters can now be marked as hidden
+- Allow setting either `defaultToneId` or `defaultVolume` in Sound Switch CC
+
+#### Bugfixes
+
+- Remove overly strict ASCII event data padding validation in Entry Control CC
+- Fixed an issue where an (unexpected) "Node ID added" notification during an ongoing inclusion would cause security bootstrapping to be skipped
+- The `lastSeen` field is now restored when initializing node statistics
+- Spec compliance: use `Extended User Code Set` to control V2+ devices
+
+#### Config file changes
+
+- Omit `dimmingDuration` field for TKBHome Dimmer
+- Add Heatit Z-TRM6 DC Thermostat
+
+### Z-Wave JS 15.17.1
+
+#### Bugfixes
+
+- Fixed an error that could happen when receiving an S0 Nonce Report before the request acknowledgement
+
+### Z-Wave JS 15.17.0
+
+#### Features
+
+- Add rudimentary support for Application Status Command Class
+- Implement `refreshValues` for Window Covering CC
+
+#### Bugfixes
+
+- Add missing "Panic alert" event to "Emergency Alarm" notification
+- Fixed an issue where Basic CC values were incorrectly exposed after including a device
+- Fixed an error that could happen when receiving an S2 Nonce Report before the request acknowledgement
+- Cached user codes are now cleared when an "All user codes deleted" notification is received
+- For notification sensors operating in push mode, the notification state is now queried during the interview
+- Fixed a regression where value changes were not verified on slow devices after immediately successful supervised commands
+
+#### Config file changes
+
+- Add Shelly Wave Shutter, update Wave 1, Wave 1PM, Wave 2PM, Wave Plug S
+- Add product id `0x03b9` to Kwikset 918
+- Update documentation link for Eurotronic Comet Z
+- Add Philips DDL240X Touchscreen Deadbolt
+- Add US variant to Shelly Wave 2PM
+
+### Z-Wave JS 15.16.0
+
+#### Features
+
+- Config parameter values can now be marked as recommended and automatically be set during the interview
+- Config parameters can now be marked as destructive, allowing applications to confirm before setting them
+- Add API to enable more frequent background RSSI measurements
+
+#### Bugfixes
+
+- Battery CC reports with invalid levels are now discarded
+
+#### Config file changes
+
+- Add fingerprint to Kwikset HC-620
+- Add Zooz ZSE11 800LR
+- Add version conditionals and correct parameters for Enbrighten 55258
+- Replace wrong troubleshooting link in 700 series firmware warning template
+- Add Kwikset 918
+- Correct user code slot bit field for BE468ZP/BE469/BE469ZP
+- Add parameters 3, 40 and 84 for Enbrighten 55258, firmware version 5.51
+
+### Z-Wave JS 15.15.2
+
+#### Bugfixes
+
+- Fixes a rare issue with the cache serialization of certain values that could lead to out-of-memory crashes, often immediately or shortly after startup
+
+#### Config file changes
+
+- Add Namron 4512774 Remote Controller
+
+### Z-Wave JS 15.15.1
+
+#### Bugfixes
+
+- Fixed a warning in bundlers about an unexpected `node:net` import
+- Fixed an issue where the device class of newly joined devices would not be persisted, causing legacy secure devices not to be automatically included with encryption
+
+#### Config file changes
+
+- Update parameters for HomeSeer WS300
+- Add Zooz ZEN78 High Power Relay
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.15.0...15.19.0](https://github.com/zwave-js/zwave-js/compare/v15.15.0...v15.19.0)
+
+## 0.27.0
+
+### Changes
+
+- Revert automatic reconnection when communication with adapter is lost. Home Assistant already handles this.
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.4.0](https://github.com/zwave-js/zwave-js-server/releases/tag/3.4.0)
+
+## 0.26.0
+
+### Features
+
+- Support creating mixed LR and non-LR "multicast" groups
+
+### Bugfixes
+
+- IP based connections no longer block the process for several minutes on connection failures/timeouts
+- Disable optimistic value updates for slow device classes, like shades and gates
+- Fixed an edge case where support for EU Long Range is not inferred correctly
+- During route rebuilds, invalid and non-existing association targets are now skipped instead of failing the whole process
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.15.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.15.0)
+
+## 0.25.0
+
+### Features
+
+- Try re-establishing connection when communication with adapter is lost
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.3.0](https://github.com/zwave-js/zwave-js-server/releases/tag/3.3.0)
+
+## 0.24.0
+
+### Features
+
+- Allow configuring a socket as an alternative to a device
+
+### Bugfixes
+
+- Fixed an issue where converting NVMs with unknown objects would fail due to unknown NVM section
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.14.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.14.0)
+
+## 0.23.0
+
+### Features
+
+- Support checking for all firmware updates at once, and support detecting devices unknown to the firmware update service
+
+### Bugfixes
+
+- Fixed an edge case preventing the migration of some controllers
+- Clean up Battery "isLow" values that are no longer updated by the Z-Wave JS driver
+
+### Config file changes
+
+- Added support for Zooz ZEN75
+- Updated Inovelli VZW32-SN device support to match latest firmware
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.13.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.13.0)
+
+## 0.22.0
+
+### Features
+
+- Firmware updates that fail due to an XMODEM communication error are now retried automatically, reducing the risk to get stuck in bootloader until a new firmware is flashed (#8086)
+
+### Bugfixes
+
+- Fixes an issue where the controller would indefinitely be considered as recovering from a jammed state, preventing commands from being re-transmitted (#8052)
+- Fixed an issue where the key up event would be force-emitted too early on legacy devices that incorrectly report not to support the "slow refresh" capability (#8087)
+- Canceling a "replace failed node" operation no longer prevents other inclusion/exclusion operations from being started (#8084)
+
+### Config file changes
+
+- Add HomeSeer WS300 (#8074)
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.12.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.12.0)
+
+## 0.21.0
+
+### Features
+
+- Z-Wave JS: Add support for defining Scene labels in config files
+- Z-Wave JS: Disable SmartStart provisioning entries after 5 failed inclusion attempts
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue where Aeotec Z-Stick 5 would become unresponsive during NVM backup
+- Z-Wave JS: Fixed firmware update progress jumping back and forth
+- Z-Wave JS: Fixed incorrect long-term averaging of RSSI values
+- Z-Wave JS: Ensure failures during NVM migration are surfaced to the application
+
+### Config file changes
+
+- Prepare Inovelli VZW31-SN for future firmware upgrade
+- Add productID `0x0111` to Fakro AMZ Solar awning
+- Add ECO-DIM.07 800 series version
+- Update Aeotec Trisensor 8 to firmware 2.8.4
+- Remove non-existent parameter 107 for Shelly Wave Plus S
+- Fix typo in Shelly dimmer output label
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.11.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.11.0)
+
+## 0.20.0
+
+### Features
+
+- Z-Wave JS Server: Bump schema to 44
+- Z-Wave JS Server: Support OTW updates through the FW update service
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.2.1](https://github.com/zwave-js/zwave-js-server/releases/tag/3.2.1)
+- [Z-Wave JS Server 3.2.0](https://github.com/zwave-js/zwave-js-server/releases/tag/3.2.0)
+
+## 0.19.0
+
+### Features
+
+- Z-Wave JS: Convert Battery CC `isLow` value to a notification
+- Z-Wave JS: Removed several unnecessary Indicator CC values and fixed several remaining ones
+
+### Bug fixes
+
+- Z-Wave JS: Use configured RF region as fallback for firmware update checks on older controllers
+- Z-Wave JS: When turning on a Multilevel Switch with supervision, the actual value is now queried immediately instead of 5s later
+
+### Config file changes
+
+- Add fingerprint to FireAngel ZHT-630, add FireAngel ZST-630
+- Remove unlock mapping for Schlage lock FE599
+- Add Fantem FT117 range extender
+- Add Zooz ZEN35
+- Remove proprietary RGB functionality for ZWA-2
+- Update label and description for ZWA-2
+- Add missing parameter 117 (Reboot) on Shelly Wave Plug S EU (QNPL-0A112)
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.10.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.10.0)
+
+## 0.18.0
+
+### Features
+
+- Z-Wave JS: Automatically correct the transmit power of adapters set to the SDK default powerlevels
+- Z-Wave JS: Reduced the need to re-interview devices after a configuration file update
+- Z-Wave JS: Avoid multi-second communication delays when pinging unreachable devices
+
+### Bug fixes
+
+- Z-Wave JS: The progress for rebuilding routes ignores Long Range devices
+- Z-Wave JS: Improved reliability of inclusion, exclusion, removing and replacing failed devices
+
+### Config file changes
+
+- Add First Alert Smart Smoke & CO Alarm
+- Add Inovelli VZW32-SN mmWave Switch
+- Update and correct Leviton device metadata
+- Add params for Enbrighten (Jasco) 59337 and 59338
+- Add fingerprint `0x8101:0x4a36` to McoHome MH4936
+- Improve accuracy of N4002/N4012 rate parameter labels
+- Add Aeotec Z-Stick 10 Pro
+- Fixed an issue with Yale YRD226 and similar locks where the number of user codes was not stored during the interview
+- Add Shelly Wave Dimmer, Motion and H&T
+- Clean up inclusion/exclusion/reset instructions in many config files
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.9.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.9.0)
+- [Z-Wave JS 15.8.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.8.0)
+- [Z-Wave JS 15.7.0](https://github.com/zwave-js/zwave-js/releases/tag/v15.7.0)
+
+## 0.17.0
+
+### Features
+
+- Z-Wave JS Server: Add command to enable/disable the radio
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.1.0](https://github.com/zwave-js/zwave-js-server/releases/tag/3.1.0)
+
+## 0.16.0
+
+### Features
+
+- Add radio frequency power level driver configuration.
+
+## 0.15.0
+
+### Features
+
+- Z-Wave JS: Add options to set powerlevel within legal limits on region change during startup
+- Z-Wave JS: Allow the application to disable support for specific CCs
+- Z-Wave JS: Support OTW updates for the controller via the firmware update service
+- Z-Wave JS: Update Notification definitions to 2024B-3 specs
+- Z-Wave JS: Add static methods to query Door Lock CC capabilities
+- Z-Wave JS: The hardware watchdog no longer gets enabled by default, since this is now handled by recent firmwares. The corresponding driver option and preset have been deprecated.
+
+### Bug fixes
+
+- Z-Wave JS: When the serialport closes unexpectedly, try to reopen it first before throwing an error
+- Z-Wave JS: Work around missing protocol version file in NVM backed up from SDK 7.23.0 and .1
+- Z-Wave JS: The default region is no longer considered to be Europe for firmware updates
+- Z-Wave JS: Make the device ID check during OTA updates actually do something
+- Z-Wave JS: Fixed a regression from v15 where Z-Wave JS would immediately soft-reset the controller instead of retrying after an ACK timeout
+- Z-Wave JS: Fixed a type error after OTW firmware upgrade
+- Z-Wave JS: Prevent the interview of battery-powered devices to stop after the first stage when re-interviewing after a firmware update
+- Z-Wave JS: Omit empty fields from TX reports, ignore missing RSSI in routing statistics
+- Z-Wave JS: Use local time for logging to file
+
+### Config file changes
+
+- Add/update several Simon iO devices
+- Add Enbrighten (Jasco) 58446 / ZWA4013 Fan Control
+- Add Aeotec ZWA046 Home Energy Meter 8
+- Add PE653 endpoints for VSP speeds and P5043ME pool/spa mode
+- Add ZVIDAR WM25C
+- Add MCO Home MH-S314-7102
+- Add McoHome thermostats MH4936, MH5-2D and MH5-4A
+- Update Inovelli VZW31-SN to FW 1.04
+- Add param 29 (load sense) to HomePro ZDP100
+- Add Yale YDM3109A Smart Lock
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.6.0)
+- [Z-Wave JS 15.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.5.0)
+- [Z-Wave JS 15.4.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.4.2)
+- [Z-Wave JS 15.4.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.4.1)
+- [Z-Wave JS 15.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.4.0)
+
+## 0.14.0
+
+### Breaking changes
+
+- Version 0.14.0 of the add-on requires version 2025.5.0 or higher of Home Assistant Core.
+
+### Features
+
+- Add radio frequency region option to the add-on.
+
+## 0.13.1
+
+### Bug fixes
+
+- Z-Wave JS Server: Fix to reuse the driver's ConfigManager instance instead of creating a new one
+- Z-Wave JS: Fixed a regression from v15 where command delivery verification wouldn't work on S2-capable devices without Supervision
+- Z-Wave JS: Fixed an issue where some CCs could be missing when Z-Wave JS was bundled
+
+### Config file changes
+
+- Disallow manual entry for param 3 on Zooz ZSE70
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.0.2](https://github.com/zwave-js/zwave-js-server/releases/tag/3.0.2)
+- [Z-Wave JS 15.3.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.3.2)
+- [Z-Wave JS 15.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.3.1)
+
+## 0.13.0
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue where incorrect device info for the controller was exposed until restarting after migration from different hardware
+- Z-Wave JS Server: Support omitting optional data while restoring NVM backups
+
+### Config file changes
+
+- Add Ness Smart Plug ZA-216001
+- Add fingerprint for FortrezZ LLC SSA1/SSA2
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.0.1](https://github.com/zwave-js/zwave-js-server/releases/tag/3.0.1)
+- [Z-Wave JS 15.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.3.0)
+- [Z-Wave JS 15.2.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.2.1)
+- [Z-Wave JS 15.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.2.0)
+
+## 0.12.1
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue where some controllers could lock up when retrying a command to an unresponsive node
+- Z-Wave JS: Several fixes for legacy Multi Channel devices
+
+### Config file changes
+
+- Add fingerprint for FortrezZ LLC SSA1/SSA2
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.1.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.1.3)
+- [Z-Wave JS 15.1.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.1.2)
+- [Z-Wave JS 15.1.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.1.1)
+
+## 0.12.0
+
+### Features
+
+- Z-Wave JS: Add support for proprietary controller functionality
+
+### Bug fixes
+
+- Z-Wave JS: Fixed two issues that could cause commands to fail with "transmit queue full" errors
+
+### Config file changes
+
+- Add ZWA-2
+
+### Detailed changelogs
+
+- [Z-Wave JS 15.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.1.0)
+- [Z-Wave JS 15.0.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.6)
+
+## 0.11.0
+
+### Breaking changes
+
+- Version 0.11.0 of the add-on requires version 2021.3.0 or higher of Home Assistant Core.
+
+### Features
+
+- Z-Wave JS / Z-Wave JS Server: Add API to query supported notification events of a device
+- Z-Wave JS Server: Support for zwave-js v15
+
+### Bug fixes
+
+- Z-Wave JS: Improved spec compliance
+- Z-Wave JS: Fixed an issue where multi-stage firmware updates would fail after the first stage
+- Z-Wave JS: Fixes an issue where no firmware updates would show as available when the controller region is set to EU_LR
+
+### Config file changes
+
+- Add alarmType 132 mapping for Yale YRD4x0 locks
+- Add fingerprint for ZVIDAR Z-TRV-V01
+- Add missing parameters to Qubino Smart Plug 16A
+- Add missing parameters for the MCO MH-C221 shutter
+- Correct Fibaro FGMS001 association groups
+- Add multi-click detection parameter to Zooz ZEN51/52
+- Add Shelly Door/Window Sensor, Wave Plug S, Wave PRO Dimmer 1PM/2PM
+- Add SmartWings WB04V
+- Add new parameters for Zooz ZEN72 firmware 3.40 and 3.50
+- Add new Zooz ZEN32 parameter 27
+- Update New One N4002 to correct parameters and other information
+- Update Zooz ZSE44 based on latest docs
+- Add SmartWings WM25L Smart Motor
+- Update Zooz ZEN04 to firmware 2.30
+- Update Zooz ZEN30 to Firmware v4.20
+- Update Zooz ZEN20 to firmware 4.20
+- Update Zooz ZEN17 800LR to firmware 2.0
+- Update to TKB Home TZ88
+- Add missing and new parameters for Zooz ZEN15
+- Add fingerprint to Yale YRL210
+- Add Springs Window Fashions CRBZ motorized blinds
+- Add Jasco ZWN4015 In-Wall Smart Switch
+- Add config parameters to Schlage PIR Motion Sensor
+- Add Lockly Secure Plus
+- Update Zooz ZEN74 to firmware 2.10
+- Preserve endpoints for Namron 16A thermostats
+- Allow setting arbitrary Motion Sensitivity for ZSE70
+- Update config file for 500 series controllers
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 3.0.0](https://github.com/zwave-js/zwave-js-server/releases/tag/3.0.0)
+- [Z-Wave JS 15.0.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.5)
+- [Z-Wave JS 15.0.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.4)
+- [Z-Wave JS 15.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.3)
+- [Z-Wave JS 15.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.2)
+- [Z-Wave JS 15.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.1)
+- [Z-Wave JS 15.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v15.0.0)
+- [Z-Wave JS 14.3.13](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.13)
+- [Z-Wave JS 14.3.12](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.12)
+- [Z-Wave JS 14.3.11](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.11)
+- [Z-Wave JS 14.3.10](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.10)
+- [Z-Wave JS 14.3.9](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.9)
+
+## 0.10.0
+
+### Features
+
+- Z-Wave JS Server: Forward driver ready event
+- Z-Wave JS Server: Support controller.cancelSecureBootstrapS2
+- Z-Wave JS Server: Support zwave-js v14
+- Z-Wave JS: Allow specifying RF region for OTA firmware updates if the region is unknown or cannot be queried
+- Z-Wave JS: Add tryUnzipFirmwareFile utility to support zipped OTA firmware files
+
+### Bug fixes
+
+- Z-Wave JS Server: Fix stringify Uint8Arrays like Buffers
+- Z-Wave JS: Fixed firmware updates fail to start on some devices with error "invalid hardware version"
+- Z-Wave JS: Fixed another issue where some CC API methods would incorrectly fail validation of their arguments, causing the node interview to fail
+- Z-Wave JS: Fixed an issue that prevented the nvmedit CI utility from starting
+- Z-Wave JS: Fixed an issue where some CC API methods would incorrectly fail validation of their arguments
+- Z-Wave JS: Fixed an issue where CC classes would have a different name when zwave-js was loaded as CommonJS, changing how those CCs were handled
+- Z-Wave JS: Fix parsing of some older 500 series NVM formats
+- Z-Wave JS: Fixed an issue where mock-server would not start due to an incorrect module format
+- Z-Wave JS: Fixed an issue where the auto-generated argument validation for CC API methods would not work correctly in some cases when zwave-js was bundled
+- Z-Wave JS: Fixed an issue where encoding a buffer as an ASCII string would throw an error on Node.js builds without full ICU
+- Z-Wave JS: Parse negative setback state consistently
+- Z-Wave JS: Ignore LR nodes when computing neighbor discovery timeout
+- Z-Wave JS: Automatically fall back to Europe when setting region to Default (EU)
+
+### Config file changes
+
+- Preserve all endpoints for Fibaro FGFS101, FW 26.26
+- Preserve all endpoints for Fibaro FGFS101, FW 25.25
+- Updates to AEON Labs Minimote
+- Auto-assign Lifeline for Trane XL624
+- Disable Supervision for Everspring SP817 Motion Sensor
+- Add wakeup instructions for ZSE43
+- Add wakeup instructions for ZSE42
+- Add wakeup instructions for ZSE41
+- Add Zooz ZSE70 800LR
+- Add new device config for Philips DDL240X-15HZW lock
+- Add Z-Wave.me Z-Station
+- Add HomeSys HomeMech-2001/2
+- Ignore setpoint range for Ecolink TBZ500
+- Add Aeotec TriSensor 8
+- Disable Supervision for Everspring SE813
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 1.40.3](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.3)
+- [Z-Wave JS Server 1.40.2](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.2)
+- [Z-Wave JS Server 1.40.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.0)
+- [Z-Wave JS 14.3.8](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.8)
+- [Z-Wave JS 14.3.7](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.7)
+- [Z-Wave JS 14.3.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.6)
+- [Z-Wave JS 14.3.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.5)
+- [Z-Wave JS 14.3.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.4)
+- [Z-Wave JS 14.3.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.3)
+- [Z-Wave JS 14.3.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.2)
+- [Z-Wave JS 14.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.1)
+- [Z-Wave JS 14.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.2.0)
+- [Z-Wave JS 14.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.1.0)
+- [Z-Wave JS 14.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.0.0)
+- [Z-Wave JS 13.10.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.3)
+
+## 0.9.0
+
+### Features
+
+- Z-Wave JS: mock-server now supports putting the simulated controller into add and remove mode
+- Z-Wave JS Server: Support get_raw_config_parameter_value
+- Z-Wave JS Server: Support all signatures of node.manuallyIdleNotificationValue
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue where preferred scales were not being found when set as a string
+- Z-Wave JS: Correct unit of Meter CC values
+- Z-Wave JS: Bootloader mode is now detected even when short chunks of data are received
+- Z-Wave JS: Corrected the wording of idle/busy queue logging
+
+### Config file changes
+
+- Add Heatit Z-TEMP3
+- Add new parameters 17 and 18 for HeatIt TF016_TF021 FW 1.92
+- Disable Supervision for Heatit TF021
+- Add ZVIDAR WB04V Smartwings Day Night Shades
+- Add ZVIDAR WM25L Smartwings Smart Motor
+- Add ZVIDAR ZW881 Multi-Protocol Gateway
+- Add include, exclude, and wakeup instructions for VCZ1
+- Add new Product ID to Namron 16A Switch
+- Add Minoston MP24Z 800LR Outdoor Smart Plug - 2 Outlet
+- Disable Supervision for Everspring SE813
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 1.39.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.39.0)
+- [Z-Wave JS 13.10.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.3)
+- [Z-Wave JS 13.10.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.2)
+- [Z-Wave JS 13.10.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.1)
+- [Z-Wave JS 13.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.0)
+- [Z-Wave JS 13.9.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.9.1)
+
+## 0.8.1
+
+Rename Z-Wave watchdog option to avoid confusion with add-on watchdog.
+
+## 0.8.0
+
+### Features
+
+- Add-on: Add `disable_watchdog` configuration option. When enabled, the driver will not enable the hardware watchdog of the Z-Wave controller. This is an advanced configuration option that should not be adjusted in most cases and is therefore hidden from the default view.
+- Z-Wave JS: Multiple parallel firmware updates are now supported
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue where open/close for some covers was inverted
+
+### Config file changes
+
+- Update Z-Wave SDK warnings to mention recommended versions
+- Update Zooz device labels
+- Add fingerprint to Aeotec ZWA024
+- Correct max. value of SKU parameters for Kwikset locks
+- Add fingerprint to Remotec ZXT-800
+- Add incompatibility warning to UZB1
+- Override Central Scene CC version for Springs Window Fashions VCZ1
+- Add manual and reset metadata for Danfoss LC-13
+
+### Detailed changelogs
+
+- [Z-Wave JS 13.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.4.0)
+- [Z-Wave JS 13.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.5.0)
+- [Z-Wave JS 13.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.6.0)
+- [Z-Wave JS 13.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.7.0)
+- [Z-Wave JS 13.8.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.8.0)
+- [Z-Wave JS 13.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.9.0)
+
+## 0.7.2
+
+### Bug fixes
+
+- Z-Wave JS: Fixed the identification of the primary controller role on some older controllers
+- Z-Wave JS: Fixed an issue where passing a custom log transport to updateOptions would cause a call stack overflow
+- Z-Wave JS: Implement deserialization for more WindowCoveringCC commands to be used in mocks
+
+### Config file changes
+
+- Add Philio Technology Smart Keypad
+- Add LED indication parameter for Inovelli NZW31 dimmer
+
+### Detailed changelogs
+
+- [Z-Wave JS 13.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.3.1)
+
+## 0.7.1
+
+### Bug fixes
+
+- Add-on: Fix the soft reset driver option that was moved in driver v.13.
+
+## 0.7.0
+
+### Features
+
+- Z-Wave JS: Add support for EU Long Range
+- Z-Wave JS: Support learn mode to become a secondary controller
+- Z-Wave JS: Add method to query supported RF regions and their info
+- Z-Wave JS: Support Firmware Update Meta Data CC v8
+- Z-Wave JS: Implement 32-bit addressed NVM operations
+- Z-Wave JS: Add methods to reset SPAN of one or all nodes
+- Z-Wave JS: Add method to enumerate all device classes
+- Z-Wave JS: Update list of manufacturers and existing CCs
+- Z-Wave JS: Add inclusion state changed event
+- Z-Wave JS: Add support for new notifications
+- Z-Wave JS: Bump version of Association CC and Multi Channel Association CC
+- Z-Wave JS: Add link reliability check feature
+- Z-Wave JS: Enable hardware watchdog on 700/800 series controllers
+- Z-Wave JS: Add method to query supported RF regions
+- Z-Wave JS: Add notification variable for Door/Window tilt state
+
+### Bug fixes
+
+- Z-Wave JS: Fix missing values in endpoint dump
+- Z-Wave JS: Preserve granted security classes of provisioning entries when switching protocols
+- Z-Wave JS: Version of Humidity Control Mode CC is 1, not 2
+- Z-Wave JS: Abort S2 bootstrapping when KEXSetEcho has reserved bits set
+- Z-Wave JS: Fixed an issue causing non-implemented CCs to be dropped before applications could handle them
+- Z-Wave JS: Fixed an issue causing all ZWLR multicast groups to be considered identical
+- Z-Wave JS: Fixed a startup crash on Zniffers older than FW 2.55
+- Z-Wave JS: Fixed latency calculation in link reliability check, distinguish between latency and RTT
+- Z-Wave JS: Fixed a regression that could cause incorrect units and missing sensor readings
+- Z-Wave JS: Don't verify delivery of S2 frames in link reliability check
+- Z-Wave JS: Reset aborted flags when starting link reliability or route health check
+- Z-Wave JS: Supported CCs of endpoints are now reset during a re-interview
+- Z-Wave JS: Basic CC is no longer automatically marked as supported if included in the list of securely supported commands
+- Z-Wave JS: Set highest version also for Basic CC if Version CC is not supported
+- Z-Wave JS: Fixed an issue where CC values could be returned for the controller node
+- Z-Wave JS: Fixed a regression from v12.12.3 would result in Basic CC values being exposed unnecessarily for some devices
+- Z-Wave JS: Fixed an issue where Basic CC values would be exposed unnecessarily for devices with a compat flag that maps Basic CC Set to a different CC
+- Z-Wave JS: When responding to Version CC Get queries, Z-Wave JS's own version is now included as the Firmware 1 version
+- Z-Wave JS: When receiving a notification with an unknown notification type, the created "unknown" value now correctly has metadata set
+- Z-Wave JS: When receiving an idle notification, the values for unknown notification events are now also reset to idle
+- Z-Wave JS: Auto-enable all supported Barrier Operator signaling subsystem during the interview
+- Z-Wave JS: Fixed an issue where the watchdog feature could cause Z-Wave JS to stall after attempting controller recovery
+- Z-Wave JS: Reset controller again when transmitting to a problematic node makes the controller become unresponsive again after automatic recovery
+- Z-Wave JS: Node interviews are now aborted in more cases when node is determined to be dead
+- Z-Wave JS: Expose Basic CC currentValue when certain compat flags are set
+- Z-Wave JS: Fixed an issue where value metadata for unknown notification events with known notification types would only be created if the CC version was exactly 2
+
+### Config file changes
+
+- Add new fingerprint for TZ45 thermostat
+- Add alarm mapping for Schlage lock CKPD FE599
+- Add fingerprint for Climax Technology SDCO-1
+- Add Shelly Wave Pro 3 and Wave Pro Shutter
+- Remove endpoint workaround for Zooz ZEN30, FW 3.20+
+- Add ZVIDAR ZW872 800 series Pi Module
+- Add ZVIDAR ZW871 800 series USB Controller
+- Rename Zvidar config file name Z-PI to Z-PI.json
+- Update Zooz ZEN30 to latest revisions
+- Support MCO Home MH-S412 parameters properly
+- Add Ring Flood Freeze Sensor
+- Override user code count for Yale ZW2 locks to expose admin code
+- Add GDZW7-ECO Ecolink 700 Series Garage Door Controller
+- Correct label for Remote 3-Way Switch parameter on Zooz ZEN32
+- Add UltraPro 700 Series Z-Wave In-Wall Smart Dimmer
+- Add Yale Assure 2 Biometric Deadbolt locks
+- Add iDevices In-Wall Smart Dimmer
+- Support Comet parameters properly
+- Update label of Nortek GD00Z-6, -7, -8
+- Disable Supervision for Zooz ZSE11
+- Clarify parameters and units for Everspring AN158
+- Force-add support for Multilevel Switch CC to FGRM-222, remove Binary Switch CC
+- Add ZVIDAR Z-PI 800 Series PI Module
+
+### Detailed changelogs
+
+- [Z-Wave JS 13.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.3.0)
+- [Z-Wave JS 13.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.2.0)
+- [Z-Wave JS 13.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.1.0)
+- [Z-Wave JS 13.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.3)
+- [Z-Wave JS 13.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.2)
+- [Z-Wave JS 13.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.1)
+- [Z-Wave JS 13.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.0)
+- [Z-Wave JS 12.13.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.13.0)
+- [Z-Wave JS 12.12.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.5)
+- [Z-Wave JS 12.12.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.4)
+- [Z-Wave JS 12.12.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.3)
+- [Z-Wave JS 12.12.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.2)
+- [Z-Wave JS 12.12.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.1)
+- [Z-Wave JS 12.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.0)
+
+## 0.6.2
+
+### Bug fixes
+
+- Z-Wave JS: Fixed a regression causing commands to sleeping nodes to block communication with other nodes
+
+### Detailed changelogs
+
+- [Z-Wave JS 12.11.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.2)
+
+## 0.6.1
+
+### Bug fixes
+
+- Z-Wave JS: When attempting communication with a node that's considered dead, the command is now sent immediately instead of pinging first
+- Z-Wave JS: Fixed prioritization of queued transactions once a node wakes up
+
+### Config file changes
+
+- Remove endpoint workaround for Zooz ZEN30 800LR
+- Encode CCs using target's CC version for TKB Home TZ67
+
+### Detailed changelogs
+
+- [Z-Wave JS 12.11.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.1)
+
+## 0.6.0
+
+### Features
+
+- Z-Wave JS: Map more Basic CC values to more useful command classes
+- Z-Wave JS: Automatically prefer ZWLR-capable RF regions over their non-ZWLR counterparts
+- Z-Wave JS: Add driver option to configure vendor-specific constants Z-Wave JS uses to reply to requests from other nodes, including manufacturer ID, product type/ID and hardware version
+
+### Bug fixes
+
+- Z-Wave JS: NVM restore now works around an issue that affects some 800 series controllers
+- Z-Wave JS: More gracefully handle scenario where inclusion couldn't be completed due to missing security keys
+- Z-Wave JS: Fixed an issue where excluded ZWLR nodes were not removed from the list of nodes until restart
+- Z-Wave JS: Always query Basic CC version as part of the interview
+- Z-Wave JS: Add support for Z-Wave Long Range devices in NVM backup and restore
+- Z-Wave JS: Abort S2 bootstrapping when CSA is requested (not supported in Z-Wave JS)
+- Z-Wave JS: Implement workaround to recover jammed controller by soft-resetting
+- Z-Wave JS: Fixed a race condition that would cause a timeout error to be shown after an actually successful OTW update
+
+### Config file changes
+
+- Add HomeSeer PS100 presence sensor, fix broken links
+- Fix value size for Fibaro FGWCEU-201, params 150/151
+- Disable Supervision for Heatit Z-Temp2, firmware 1.2.1
+- Use specific float encoding for Namron 4512757
+- Add fingerprint for Aeotec MultiSensor 7
+- Override CC versions for Wayne Dalton WDTC-20
+- Disable Supervision for Everspring EH403
+- Add parameter 117 to Shelly Wave Plug US and UK
+- Add params 12, 20, 254 for Aeotec DSB09
+- Use HomeSeer template for LED Indicator (parameter 3) for all HomeSeer switches
+- Add Fibaro FGR-224 Roller Shutter 4
+- Parameter update for Zooz Zen16 v2.0 and v2.10
+- Override Central Scene CC version for Springs Window Fashions BRZ
+- Add fingerprint 0x0004:0xffff to "Yale YRD210"
+- Correct config parameters for Minoston MP21ZD Dimmer Plug
+
+### Detailed changelogs
+
+- [Z-Wave JS 12.11.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.0)
+- [Z-Wave JS 12.10.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.10.1)
+- [Z-Wave JS 12.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.10.0)
+- [Z-Wave JS 12.9.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.9.1)
+- [Z-Wave JS 12.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.9.0)
+- [Z-Wave JS 12.8.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.8.1)
+- [Z-Wave JS 12.8.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.8.0)
+- [Z-Wave JS 12.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.7.0)
+- [Z-Wave JS 12.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.6.0)
+- [Z-Wave JS 12.5.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.6)
+
+## 0.5.0
+
+### Features
+
+- Z-Wave JS: Map more Basic CC values to more useful command classes
+- Z-Wave JS: Add Z-Wave Long Range support
+- Z-Wave JS Server: Add Z-Wave Long Range support
+- Addon: Add support for collecting Z-Wave Long Range security keys
+
+### Bug fixes
+
+- Z-Wave JS: Fixed an issue that caused additional invalid values to be discovered
+- Z-Wave JS: Fixed a crash that could happen in some cases during the Configuration CC interview
+- Z-Wave JS: Fixed an issue where provisioning entries could disappear
+- Z-Wave JS: Fixed an infinite loop during NVM migration which could happen in rare cases
+- Z-Wave JS: Firmware updates on Z-Wave Long Range now utilize the larger frame size better
+- Z-Wave JS: Fixed an issue with multicast setValue response
+- Z-Wave JS: Disallow associating a node with itself and skip self-associations when rebuilding routes
+
+### Config file changes
+
+- Always map Basic CC to Binary Sensor CC for Aeotec ZW100 Multisensor 6
+- Fix versioning logic for parameter 26 of Zooz ZEN72
+- Add new Leviton 800 series devices
+- Add UltraPro Z-Wave Plus In-Wall Toggle Switch, 700S
+- Rename generic 700 series controller to include 800 series
+- Add fingerprint and config parameters for UltraPro 700 Switch
+- Add Zooz Zen37 800LR Wall Remote
+- Added 11 Shelly Qubino Wave devices
+- Add Heatit Leakage Water Stopper
+- Add Ring Smoke/CO Listener
+- Add ZVIDAR Z-TRV-V01 thermostatic valve
+- Add Safe Grow NSG-AB-02 Z-Wave Plus Smart Outlet Plug
+- Add a new productId and add parameters to 14297/ZW1002 outlet
+- Remove Association Groups 2 & 3 from AEON Labs DSB09
+- Correct group 3 label for GE/Enbrighten 26931/ZW4006
+- Add new Fingerprint for Ring Contact sensor
+- Preserve root endpoint in Vision ZL7432
+- Add new Product ID to Fibaro Smoke Detector
+- Add Product ID for Benext Energy Switch FW1.6
+- Add fingerprint for Ring Glass Break Sensor EU
+- Change MH9-CO2 Temperature Reporting Threshold step size to 0.1
+- Add new product ID to Fibaro FGS-213
+- Add units, improve descriptions for Everspring ST814
+- Label and parameter definitions for Sensative Drip 700
+- Override supported sensor scales for HELTUN HE-ZW-THERM-FL2
+
+### Detailed changelogs
+
+- [Z-Wave JS Server 1.35.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.35.0)
+- [Z-Wave JS 12.5.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.5)
+- [Z-Wave JS 12.5.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.4)
+- [Z-Wave JS 12.5.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.3)
+- [Z-Wave JS 12.5.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.2)
+- [Z-Wave JS 12.5.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.1)
+- [Z-Wave JS 12.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.0)
+
## 0.4.5
### Bug fixes
@@ -212,7 +1170,6 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Fixes or works around multiple issues with 500 series controllers that could trigger the unresponsive controller detection in Z-Wave JS 12 in situations where it was not necessary, causing restart loops.
-
### Bug fixes
- [Z-Wave JS 12.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.3)
@@ -230,6 +1187,7 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Ignore when a node reports Security S0/S2 CC to have version 0 (unsupported) although it is using that CC
### Config file changes
+
- Add Shelly to manufacturers
- Add Shelly Wave 1, Wave 2PM, update Wave 1PM association labels
- Add Sunricher SR-ZV2833PAC
@@ -334,7 +1292,7 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Fixed a regression from v11.10.1 where the controller's firmware version was not fully queried
- Z-Wave JS: Change order of commands so the startup does not fail when a controller is already set to use 16-bit node IDs and soft-reset is disabled
-- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers
+- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers
- Z-Wave JS: Queried user codes and their status are now preserved during re-interview when they won't be re-queried automatically
- Z-Wave JS: Fixed an issue where nodes were being marked as dead because the controller couldn't transmit.
- Z-Wave JS: Fixed an issue where 700 series controllers were not soft-reset after NVM backup when soft-reset was disabled via config
@@ -352,6 +1310,7 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Correct reporting frequency parameter values for Sensative AB Strips Comfort / Drips Multisensor
### Detailed changelogs
+
- [Bump Z-Wave JS Server to 1.31.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.31.0)
- [Bump Z-Wave JS to 11.11.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.11.0)
- [Bump Z-Wave JS to 11.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.12.0)
@@ -364,10 +1323,9 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Fixed a bug where firmware links that redirected to another URL were not supported
- Z-Wave JS: Change order of commands so the startup does not fail when a controller is already set to use 16-bit node IDs and soft-reset is disabled
-- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers
+- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers
- Z-Wave JS: Queried user codes and their status are now preserved during re-interview when they won't be re-queried automatically
-
### Config file changes
- Add parameters 9-13 to Minoston MP21ZP / MP31ZP
@@ -395,7 +1353,6 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Fixed an issue where no control values were exposed for devices that do not support/advertise Version CC
- Z-Wave JS: Fixed a regression introduced in 11.9.1 that would sometimes cause the startup process to hang
-
### Config file changes
- Add Leviton RZM10-1L
@@ -433,7 +1390,6 @@ Almost 1000 device configuration files have been reworked to be more consistent,
- Z-Wave JS: Devices that failed to join using SmartStart are now automatically removed
- Z-Wave JS: Fix an issue where Z-Wave JS could get stuck when removing a node from the network failed
-
### Config file changes
- Correct config parameters for Duwi ZW ESJ 300
diff --git a/zwave_js/DOCS.md b/zwave_js/DOCS.md
index bd75b4b2ed0..4e1bfd9d004 100644
--- a/zwave_js/DOCS.md
+++ b/zwave_js/DOCS.md
@@ -1,24 +1,24 @@
-# Home Assistant Add-on: Z-Wave JS
+# Home Assistant App: Z-Wave JS
## Installation
-Follow these steps to get the add-on installed on your system:
+Follow these steps to get the app installed on your system:
-1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on Store**.
-2. Find the "Z-Wave JS" add-on and click it.
+1. In Home Assistant, go to **Settings** > **Apps** > **Install app**.
+2. Find the "Z-Wave JS" app and click it.
3. Click on the "INSTALL" button.
## How to use
-The add-on needs to know where your Z-Wave stick can be found, and therefore,
-you'll need to configure the add-on to point to the right device.
+The app needs to know where your Z-Wave stick can be found, and therefore,
+you'll need to configure the app to point to the right device.
If you're using Home Assistant you may find the correct value for this by going to
`Settings -> System -> Hardware` and then clicking the three dots menu and selecting
`All Hardware`. It is recommended to use a "by-id" path to the device if one exists,
as it is not subject to change if other devices are added to the system.
-1. Replace `null` in the `device` option in the add-on configuration and specify
+1. Replace `null` in the `device` option in the app configuration and specify
the device name in quotes: e.g., something like
`"/dev/serial/by-id/usb-0658_0200-if00"`,
`"/dev/ttyUSB0"`, `"/dev/ttyAMA0"`, or `"/dev/ttyACM0"`.
@@ -28,14 +28,14 @@ as it is not subject to change if other devices are added to the system.
may not function correctly if they are not added securely.
- As a note, it is not recommended to securely connect _all_ devices unless they support S2 security
as the S0 security triples the amount of messages sent on the mesh.
-3. Click on "SAVE" to save the add-on configuration.
-4. Start the add-on.
+3. Click on "SAVE" to save the app configuration.
+4. Start the app.
5. Add the Z-Wave JS integration to Home Assistant, see documentation:
## Configuration
-Add-on configuration:
+App configuration:
```yaml
device: /dev/ttyUSB0
@@ -43,6 +43,8 @@ s0_legacy_key: 2232666D100F795E5BB17F0A1BB7A146
s2_access_control_key: A97D2A51A6D4022998BEFC7B5DAE8EA1
s2_authenticated_key: 309D4AAEF63EFD85967D76ECA014D1DF
s2_unauthenticated_key: CF338FE0CB99549F7C0EA96308E5A403
+lr_s2_access_control_key: E2CEA6B5986C818EEC0D0065D81E2BD5
+lr_s2_authenticated_key: 863027C59CFC522A9A3C41976AE54254
```
### Option `device`
@@ -64,18 +66,18 @@ In most cases this looks like one of the following:
### Security Keys
-There are four different security keys required to take full advantage of the
+There are six different security keys required to take full advantage of the
different inclusion methods that Z-Wave JS supports: `s0_legacy_key`,
-`s2_access_control_key`, `s2_authenticated_key`, and `s2_unauthenticated_key`.
+`s2_access_control_key`, `s2_authenticated_key`, `s2_unauthenticated_key`, `lr_s2_access_control_key`, and `lr_s2_authenticated_key`.
If you are coming from a previous version of `zwave-js`, you likely have a key
-stored in the `network_key` configuration option. When the addon is first
+stored in the `network_key` configuration option. When the app is first
started, the key will be migrated from `network_key` to `s0_legacy_key` which
will ensure that your S0 secured devices will continue to function.
-If any of these keys are missing on startup, the addon will autogenerate one for
+If any of these keys are missing on startup, the app will autogenerate one for
you. To generate a network key manually, you can use the following script in,
-e.g., the SSH add-on:
+e.g., the SSH app:
```bash
hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
@@ -97,7 +99,7 @@ those devices and your controller, before rebuilding your Z-Wave network.
#### Option `s0_legacy_key`
S0 Security Z-Wave devices require a network key before being added to the network.
-This configuration option is required, but if it is unset the addon will generate
+This configuration option is required, but if it is unset the app will generate
a new one automatically on startup.
#### Option `s2_access_control_key`
@@ -105,14 +107,14 @@ a new one automatically on startup.
The `s2_access_control_key` must be provided in order to include devices with the
S2 Access Control security class. This security class is needed by devices such
as door locks and garage door openers. This configuration option is required,
-but if it is unset the addon will generate a new one automatically on startup.
+but if it is unset the app will generate a new one automatically on startup.
#### Option `s2_authenticated_key`
The `s2_authenticated_key` must be provided in order to include devices with
the S2 Authenticated security class. Devices such as security systems, sensors,
lighting, etc. can request this security class. This configuration option is
-required, but if it is unset the addon will generate a new one automatically
+required, but if it is unset the app will generate a new one automatically
on startup.
### Option `s2_unauthenticated_key`
@@ -120,9 +122,21 @@ on startup.
The `s2_unauthenticated_key` must be provided in order to include devices with
the S2 Unauthenticated security class. This is similar to S2 Authenticated, but
without verification that the correct device was included. This configuration
-option is required, but if it is unset the addon will generate a new one
+option is required, but if it is unset the app will generate a new one
automatically on startup.
+#### Option `lr_s2_access_control_key`
+
+The `lr_s2_access_control_key` must be provided in order to include devices using
+Z-Wave Long Range. This configuration option is required, but if it is unset
+the app will generate a new one automatically on startup.
+
+#### Option `lr_s2_authenticated_key`
+
+The `lr_s2_authenticated_key` must be provided in order to include devices using
+Z-Wave Long Range. This configuration option is required, but if it is unset
+the app will generate a new one automatically on startup.
+
### Option `log_level` (optional)
This option sets the log level of Z-Wave JS. Valid options are:
@@ -149,29 +163,53 @@ When `log_to_file` is true, Z-Wave JS will create a log file for each
day. This option allows you to control the maximum number of files that
Z-Wave JS will keep.
+### Option `rf_region` (optional)
+
+This setting tells the app what radio frequency region the controller should use.
+Valid options are:
+
+- Automatic
+- Australia/New Zealand
+- China
+- Europe
+- Europe (Long Range)
+- Hong Kong
+- India
+- Israel
+- Japan
+- Korea
+- Russia
+- USA
+- USA (Long Range)
+
+The default is Automatic which will try to set the correct region based on the country set in Home Assistant.
+
### Option `soft_reset` (optional)
-This setting tells the add-on how to handle soft-resets for 500 series controllers:
-1. Automatic - the add-on will decide whether soft-reset should be enabled or disabled for 500 series controllers. This is the default option and should work for most people.
+This setting tells the app how to handle soft-resets for 500 series controllers:
+
+1. Automatic - the app will decide whether soft-reset should be enabled or disabled for 500 series controllers. This is the default option and should work for most people.
2. Enabled - Soft-reset will be explicitly enabled for 500 series controllers.
3. Disabled - Soft-reset will be explicitly disabled for 500 series controllers.
-### Option `emulate_hardware` (optional)
-
-If you don't have a USB stick, you can use a fake stick for testing purposes.
-It will not be able to control any real devices.
-
-### Optional `disable_controller_recovery` (optional):
+### Option `disable_controller_recovery` (optional):
This setting will disable Z-Wave JS's automatic recovery process when the
controller appears to be unresponsive and will instead let the controller
recover on its own if it's capable of doing so. While the controller is
unresponsive, commands will start to fail and nodes may randomly get
marked as dead. If a controller is not able to recover on its own, you
-will need to restart the add-on to attempt recovery. In most cases, users
+will need to restart the app to attempt recovery. In most cases, users
will never need to use this feature, so only change this setting if you
know what you are doing and/or you are asked to.
+### Option `disable_watchdog` (optional):
+
+This setting will prevent Z-Wave JS from enabling the hardware watchdog
+on supporting controllers. In most cases, users will never need to use this
+feature, so only change this setting if you know what you are doing and/or
+you are asked to.
+
### Option `safe_mode` (optional)
This setting puts your network in safe mode, which could significantly decrease
@@ -182,19 +220,19 @@ are doing and/or you are asked to.
### Option `network_key` (deprecated)
-In previous versions of the addon, this was the only key that was needed. With
+In previous versions of the app, this was the only key that was needed. With
the introduction of S2 security inclusion in zwave-js, this option has been
deprecated in favor of `s0_legacy_key`. If still set, the `network_key` value will be
migrated to `s0_legacy_key` on first startup.
### Troubleshooting network issues
-There are several features available in the add-on that can help you in troubleshooting network issues and/or providing data to either the Home Assistant or Z-Wave JS team to help in tracing an issue:
+There are several features available in the app that can help you in troubleshooting network issues and/or providing data to either the Home Assistant or Z-Wave JS team to help in tracing an issue:
1. **Update the log level:** It is extremely helpful when opening a GitHub issue to set the `log_level` configuration option to `debug` and capture when the issue occurs.
-2. **Log to file:** The `log_to_file` and `log_max_files` configuration options allow you to enable and configure that. Note that in order to access the log files, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh add-ons among others.
-3. **Access Z-Wave JS cache:** Z-Wave JS stores information it discovers about your network in cache files so that your devices don't have to be reinterviewed on every startup. In some cases, when opening a GitHub issue, you may be asked to provide the cache files. You can access them in `/addon_configs/core_zwave_js/cache`. Note that in order to access the cache, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh add-ons among others.
-4. **Change soft reset behavior:** By default, the addon will choose whether or not to soft reset the controller at startup automatically. In most cases that shouldn't be changed, but if asked to make a change when troubleshooting an issue, you can do so using the `soft_reset` configuration option.
+2. **Log to file:** The `log_to_file` and `log_max_files` configuration options allow you to enable and configure that. Note that in order to access the log files, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh apps among others.
+3. **Access Z-Wave JS cache:** Z-Wave JS stores information it discovers about your network in cache files so that your devices don't have to be reinterviewed on every startup. In some cases, when opening a GitHub issue, you may be asked to provide the cache files. You can access them in `/addon_configs/core_zwave_js/cache`. Note that in order to access the cache, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh apps among others.
+4. **Change soft reset behavior:** By default, the app will choose whether or not to soft reset the controller at startup automatically. In most cases, that shouldn't be changed, but if asked to make a change when troubleshooting an issue, you can do so using the `soft_reset` configuration option.
5. **Disable controller recovery:** By default, if the network controller appears to be jammed, Z-Wave JS will automatically try to restore the controller to a healthy state. In most cases that shouldn't be changed, but if asked to make a change when troubleshooting an issue, you can do so using the `disable_controller_recovery` configuration option.
6. **Enable safe mode:** When Z-Wave JS is having trouble starting up, it can sometimes be hard to get useful logs to troubleshoot the issue. By setting `safe_mode` to true, Z-Wave JS may be able to start up in cases where it wouldn't with the `safe_mode` set to false. Note that enabling `safe_mode` will have a negative impact on the performance of your network and should be used sparingly.
diff --git a/zwave_js/Dockerfile b/zwave_js/Dockerfile
index 632d3a8cfbd..a969b115d1a 100644
--- a/zwave_js/Dockerfile
+++ b/zwave_js/Dockerfile
@@ -1,15 +1,15 @@
ARG BUILD_FROM
FROM ${BUILD_FROM}
-ARG ZWAVEJS_SERVER_VERSION
-ARG ZWAVEJS_VERSION
+ARG ZWAVEJS_UI_VERSION
# Environment configuration
ENV \
S6_KILL_GRACETIME=30000 \
- S6_SERVICES_GRACETIME=30000
+ S6_SERVICES_GRACETIME=30000 \
+ STORE_DIR=/config
-# Install Z-Wave JS
+# Install Z-Wave JS UI
WORKDIR /usr/src
RUN \
set -x \
@@ -22,15 +22,10 @@ RUN \
linux-headers \
python3 \
\
- && npm install --force \
- "zwave-js@${ZWAVEJS_VERSION}" \
- "@zwave-js/server@${ZWAVEJS_SERVER_VERSION}" \
+ && npm install -g "zwave-js-ui@${ZWAVEJS_UI_VERSION}" \
\
- && npm rebuild --build-from-source @serialport/bindings-cpp \
&& apk del --no-cache \
.build-dependencies
WORKDIR /
COPY rootfs /
-
-ENV PATH=/usr/src/node_modules/.bin:$PATH
diff --git a/zwave_js/README.md b/zwave_js/README.md
index 395ff0cfa8c..60ef8594a28 100644
--- a/zwave_js/README.md
+++ b/zwave_js/README.md
@@ -1,12 +1,9 @@
-# Home Assistant Add-on: Z-Wave JS
+# Home Assistant App: Z-Wave JS
Allow Home Assistant to talk to a Z-Wave Network via a USB Controller.
-![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield]
+![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield]
[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg
[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg
-[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg
-[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg
-[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg
diff --git a/zwave_js/build.yaml b/zwave_js/build.yaml
index 017e0c2f057..3e36a0ac920 100644
--- a/zwave_js/build.yaml
+++ b/zwave_js/build.yaml
@@ -1,13 +1,6 @@
---
build_from:
- aarch64: ghcr.io/home-assistant/aarch64-base:3.18
- amd64: ghcr.io/home-assistant/amd64-base:3.18
- armhf: ghcr.io/home-assistant/armhf-base:3.18
- armv7: ghcr.io/home-assistant/armv7-base:3.18
- i386: ghcr.io/home-assistant/i386-base:3.18
-codenotary:
- signer: notary@home-assistant.io
- base_image: notary@home-assistant.io
+ aarch64: ghcr.io/home-assistant/aarch64-base:3.23
+ amd64: ghcr.io/home-assistant/amd64-base:3.23
args:
- ZWAVEJS_SERVER_VERSION: 1.34.0
- ZWAVEJS_VERSION: 12.4.4
+ ZWAVEJS_UI_VERSION: 11.11.0
diff --git a/zwave_js/config.yaml b/zwave_js/config.yaml
index 306cceba433..dfbbaf089c5 100644
--- a/zwave_js/config.yaml
+++ b/zwave_js/config.yaml
@@ -1,49 +1,70 @@
---
-version: 0.4.5
+version: 1.0.0
slug: zwave_js
name: Z-Wave JS
description: Control a Z-Wave network with Home Assistant Z-Wave JS
url: https://github.com/home-assistant/addons/tree/master/zwave_js
arch:
- amd64
- - i386
- - armhf
- - armv7
- aarch64
-codenotary: notary@home-assistant.io
discovery:
- zwave_js
hassio_api: true
-homeassistant: 2021.2.0b0
+homeassistant: 2025.12.0
image: homeassistant/{arch}-addon-zwave_js
init: false
+ingress: true
+ingress_port: 8091
+ingress_stream: true
+panel_icon: mdi:z-wave
+panel_title: Z-Wave
map:
- addon_config:rw
options:
- device: null
log_level: info
log_to_file: false
log_max_files: 7
+ rf_region: Automatic
soft_reset: Automatic
s0_legacy_key: ""
s2_access_control_key: ""
s2_authenticated_key: ""
s2_unauthenticated_key: ""
+ lr_s2_access_control_key: ""
+ lr_s2_authenticated_key: ""
ports:
3000/tcp: null
+ 8091/tcp: null
schema:
- device: device(subsystem=tty)
+ device: device(subsystem=tty)?
+ socket: str?
log_level: list(silly|debug|verbose|http|info|warn|error)?
log_to_file: bool?
log_max_files: int(1,)?
+ rf_region: "list(\
+ Automatic|\
+ Australia/New Zealand|\
+ China|\
+ Europe|\
+ Europe (Long Range)|\
+ Hong Kong|\
+ India|\
+ Israel|\
+ Japan|\
+ Korea|\
+ Russia|\
+ USA|\
+ USA (Long Range))?"
soft_reset: list(Automatic|Enabled|Disabled)?
s0_legacy_key: match(|[0-9a-fA-F]{32,32})?
s2_access_control_key: match(|[0-9a-fA-F]{32,32})?
s2_authenticated_key: match(|[0-9a-fA-F]{32,32})?
s2_unauthenticated_key: match(|[0-9a-fA-F]{32,32})?
+ lr_s2_access_control_key: match(|[0-9a-fA-F]{32,32})?
+ lr_s2_authenticated_key: match(|[0-9a-fA-F]{32,32})?
network_key: match(|[0-9a-fA-F]{32,32})?
- emulate_hardware: bool?
disable_controller_recovery: bool?
+ disable_watchdog: bool?
safe_mode: bool?
stage: stable
startup: services
diff --git a/zwave_js/rootfs/etc/cont-init.d/config.sh b/zwave_js/rootfs/etc/cont-init.d/config.sh
index d84e45b6df7..afcf6b0d143 100755
--- a/zwave_js/rootfs/etc/cont-init.d/config.sh
+++ b/zwave_js/rootfs/etc/cont-init.d/config.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Generate Z-Wave JS config file
# ==============================================================================
@@ -12,6 +13,9 @@ declare s2_unauthenticated
declare log_level
declare flush_to_disk
declare host_chassis
+declare rf_region
+declare rf_region_integer
+declare rf_json
declare soft_reset
declare presets_array
declare presets
@@ -20,6 +24,275 @@ readonly DOCS_EXAMPLE_KEY_1="2232666D100F795E5BB17F0A1BB7A146"
readonly DOCS_EXAMPLE_KEY_2="A97D2A51A6D4022998BEFC7B5DAE8EA1"
readonly DOCS_EXAMPLE_KEY_3="309D4AAEF63EFD85967D76ECA014D1DF"
readonly DOCS_EXAMPLE_KEY_4="CF338FE0CB99549F7C0EA96308E5A403"
+readonly DOCS_EXAMPLE_KEY_5="E2CEA6B5986C818EEC0D0065D81E2BD5"
+readonly DOCS_EXAMPLE_KEY_6="863027C59CFC522A9A3C41976AE54254"
+
+declare -A country_rf_region_map=(
+ ["AD"]="Europe"
+ ["AE"]="Europe"
+ ["AF"]="Default (EU)"
+ ["AG"]="Default (EU)"
+ ["AI"]="Europe"
+ ["AL"]="Europe"
+ ["AM"]="Europe"
+ ["AO"]="Default (EU)"
+ ["AQ"]="Default (EU)"
+ ["AR"]="USA"
+ ["AS"]="USA"
+ ["AT"]="Europe"
+ ["AU"]="Australia/New Zealand"
+ ["AW"]="Europe"
+ ["AX"]="Europe"
+ ["AZ"]="Europe"
+ ["BA"]="Europe"
+ ["BB"]="USA"
+ ["BD"]="Default (EU)"
+ ["BE"]="Europe"
+ ["BF"]="Default (EU)"
+ ["BG"]="Europe"
+ ["BH"]="Europe"
+ ["BI"]="Default (EU)"
+ ["BJ"]="Default (EU)"
+ ["BL"]="Default (EU)"
+ ["BM"]="USA"
+ ["BN"]="Default (EU)"
+ ["BO"]="USA"
+ ["BQ"]="Europe"
+ ["BR"]="Australia/New Zealand"
+ ["BS"]="USA"
+ ["BT"]="Default (EU)"
+ ["BV"]="Europe"
+ ["BW"]="Default (EU)"
+ ["BY"]="Europe"
+ ["BZ"]="Default (EU)"
+ ["CA"]="USA"
+ ["CC"]="Default (EU)"
+ ["CD"]="Default (EU)"
+ ["CF"]="Default (EU)"
+ ["CG"]="Default (EU)"
+ ["CH"]="Europe"
+ ["CI"]="Default (EU)"
+ ["CK"]="Australia/New Zealand"
+ ["CL"]="Australia/New Zealand"
+ ["CM"]="Default (EU)"
+ ["CN"]="China"
+ ["CO"]="USA"
+ ["CR"]="Japan"
+ ["CU"]="Default (EU)"
+ ["CV"]="Default (EU)"
+ ["CW"]="Europe"
+ ["CX"]="Australia/New Zealand"
+ ["CY"]="Europe"
+ ["CZ"]="Europe"
+ ["DE"]="Europe"
+ ["DJ"]="Default (EU)"
+ ["DK"]="Europe"
+ ["DM"]="Default (EU)"
+ ["DO"]="Australia/New Zealand"
+ ["DZ"]="Hong Kong"
+ ["EC"]="Australia/New Zealand"
+ ["EE"]="Europe"
+ ["EG"]="Europe"
+ ["EH"]="Default (EU)"
+ ["ER"]="Default (EU)"
+ ["ES"]="Europe"
+ ["ET"]="Default (EU)"
+ ["FI"]="Europe"
+ ["FJ"]="Australia/New Zealand"
+ ["FK"]="Europe"
+ ["FM"]="Australia/New Zealand"
+ ["FO"]="Europe"
+ ["FR"]="Europe"
+ ["GA"]="Default (EU)"
+ ["GB"]="Europe"
+ ["GD"]="Default (EU)"
+ ["GE"]="Europe"
+ ["GF"]="Europe"
+ ["GG"]="Europe"
+ ["GH"]="Default (EU)"
+ ["GI"]="Europe"
+ ["GL"]="Default (EU)"
+ ["GM"]="Default (EU)"
+ ["GN"]="Default (EU)"
+ ["GP"]="Default (EU)"
+ ["GQ"]="Default (EU)"
+ ["GR"]="Europe"
+ ["GS"]="Europe"
+ ["GT"]="USA"
+ ["GU"]="USA"
+ ["GW"]="Default (EU)"
+ ["GY"]="Default (EU)"
+ ["HK"]="Hong Kong"
+ ["HM"]="Default (EU)"
+ ["HN"]="USA"
+ ["HR"]="Europe"
+ ["HT"]="USA"
+ ["HU"]="Europe"
+ ["ID"]="Australia/New Zealand"
+ ["IE"]="Europe"
+ ["IL"]="Israel"
+ ["IM"]="Europe"
+ ["IN"]="India"
+ ["IO"]="Europe"
+ ["IQ"]="Europe"
+ ["IR"]="Default (EU)"
+ ["IS"]="Europe"
+ ["IT"]="Europe"
+ ["JE"]="Europe"
+ ["JM"]="USA"
+ ["JO"]="Europe"
+ ["JP"]="Japan"
+ ["KE"]="Default (EU)"
+ ["KG"]="Default (EU)"
+ ["KH"]="Default (EU)"
+ ["KI"]="Australia/New Zealand"
+ ["KM"]="Default (EU)"
+ ["KN"]="USA"
+ ["KP"]="Default (EU)"
+ ["KR"]="Korea"
+ ["KW"]="Europe"
+ ["KY"]="USA"
+ ["KZ"]="Europe"
+ ["LA"]="Default (EU)"
+ ["LB"]="Europe"
+ ["LC"]="Default (EU)"
+ ["LI"]="Europe"
+ ["LK"]="Default (EU)"
+ ["LR"]="Default (EU)"
+ ["LS"]="Default (EU)"
+ ["LT"]="Europe"
+ ["LU"]="Europe"
+ ["LV"]="Europe"
+ ["LY"]="Europe"
+ ["MA"]="China"
+ ["MC"]="Europe"
+ ["MD"]="Europe"
+ ["ME"]="Europe"
+ ["MF"]="Default (EU)"
+ ["MG"]="Default (EU)"
+ ["MH"]="Australia/New Zealand"
+ ["MK"]="Europe"
+ ["ML"]="Default (EU)"
+ ["MM"]="Default (EU)"
+ ["MN"]="Default (EU)"
+ ["MO"]="Korea"
+ ["MP"]="USA"
+ ["MQ"]="Default (EU)"
+ ["MR"]="Default (EU)"
+ ["MS"]="Europe"
+ ["MT"]="Europe"
+ ["MU"]="Europe"
+ ["MV"]="Europe"
+ ["MW"]="Default (EU)"
+ ["MX"]="Default (EU)"
+ ["MY"]="Australia/New Zealand"
+ ["MZ"]="Default (EU)"
+ ["NA"]="Default (EU)"
+ ["NC"]="Australia/New Zealand"
+ ["NE"]="Default (EU)"
+ ["NF"]="Australia/New Zealand"
+ ["NG"]="Europe"
+ ["NI"]="USA"
+ ["NL"]="Europe"
+ ["NO"]="Europe"
+ ["NP"]="Default (EU)"
+ ["NR"]="Australia/New Zealand"
+ ["NU"]="Australia/New Zealand"
+ ["NZ"]="Australia/New Zealand"
+ ["OM"]="Europe"
+ ["PA"]="USA"
+ ["PE"]="Australia/New Zealand"
+ ["PF"]="Australia/New Zealand"
+ ["PG"]="Australia/New Zealand"
+ ["PH"]="Europe"
+ ["PK"]="Default (EU)"
+ ["PL"]="Europe"
+ ["PM"]="Default (EU)"
+ ["PN"]="Europe"
+ ["PR"]="USA"
+ ["PT"]="Europe"
+ ["PW"]="Australia/New Zealand"
+ ["PY"]="Australia/New Zealand"
+ ["QA"]="Europe"
+ ["RE"]="Default (EU)"
+ ["RO"]="Europe"
+ ["RS"]="Europe"
+ ["RU"]="Russia"
+ ["RW"]="Default (EU)"
+ ["SA"]="Europe"
+ ["SB"]="Australia/New Zealand"
+ ["SC"]="Default (EU)"
+ ["SD"]="Default (EU)"
+ ["SE"]="Europe"
+ ["SG"]="Korea"
+ ["SH"]="Europe"
+ ["SI"]="Europe"
+ ["SJ"]="Europe"
+ ["SK"]="Europe"
+ ["SL"]="Default (EU)"
+ ["SM"]="Europe"
+ ["SN"]="Default (EU)"
+ ["SO"]="Default (EU)"
+ ["SR"]="USA"
+ ["SS"]="Default (EU)"
+ ["ST"]="Default (EU)"
+ ["SV"]="Australia/New Zealand"
+ ["SX"]="Europe"
+ ["SY"]="Default (EU)"
+ ["SZ"]="Default (EU)"
+ ["TC"]="USA"
+ ["TD"]="Default (EU)"
+ ["TF"]="Default (EU)"
+ ["TG"]="Default (EU)"
+ ["TH"]="Korea"
+ ["TJ"]="Default (EU)"
+ ["TK"]="Australia/New Zealand"
+ ["TL"]="Default (EU)"
+ ["TM"]="Europe"
+ ["TN"]="Default (EU)"
+ ["TO"]="Australia/New Zealand"
+ ["TR"]="Europe"
+ ["TT"]="USA"
+ ["TV"]="Australia/New Zealand"
+ ["TW"]="Korea"
+ ["TZ"]="Default (EU)"
+ ["UA"]="Europe"
+ ["UG"]="Default (EU)"
+ ["UM"]="USA"
+ ["US"]="USA"
+ ["UY"]="Australia/New Zealand"
+ ["UZ"]="Europe"
+ ["VA"]="Europe"
+ ["VC"]="Default (EU)"
+ ["VE"]="Australia/New Zealand"
+ ["VG"]="USA"
+ ["VI"]="USA"
+ ["VN"]="Australia/New Zealand"
+ ["VU"]="Australia/New Zealand"
+ ["WF"]="Australia/New Zealand"
+ ["WS"]="Australia/New Zealand"
+ ["YE"]="Europe"
+ ["YT"]="Default (EU)"
+ ["ZA"]="Europe"
+ ["ZM"]="Default (EU)"
+ ["ZW"]="Default (EU)"
+)
+
+declare -A rf_region_integer_map=(
+ ["Europe"]=0
+ ["USA"]=1
+ ["Australia/New Zealand"]=2
+ ["Hong Kong"]=3
+ ["India"]=5
+ ["Israel"]=6
+ ["Russia"]=7
+ ["China"]=8
+ ["USA (Long Range)"]=9
+ ["Europe (Long Range)"]=11
+ ["Japan"]=32
+ ["Korea"]=33
+ ["Default (EU)"]=255
+)
if bashio::config.has_value 'network_key'; then
# If both 'network_key' and 's0_legacy_key' are set and keys don't match,
@@ -33,7 +306,7 @@ if bashio::config.has_value 'network_key'; then
else
bashio::log.fatal "Both 'network_key' and 's0_legacy_key' are set to different values "
bashio::log.fatal "so we are unsure which one to use. One needs to be removed from the "
- bashio::log.fatal "configuration in order to start the addon."
+ bashio::log.fatal "configuration in order to start the app."
bashio::exit.nok
fi
# If we get here, 'network_key' is set and 's0_legacy_key' is not set so we need
@@ -48,23 +321,23 @@ fi
# Validate that no keys are using the example from the docs and generate new random
# keys for any missing keys.
-for key in "s0_legacy_key" "s2_access_control_key" "s2_authenticated_key" "s2_unauthenticated_key"; do
+for key in "s0_legacy_key" "s2_access_control_key" "s2_authenticated_key" "s2_unauthenticated_key" "lr_s2_access_control_key" "lr_s2_authenticated_key"; do
network_key=$(bashio::config "${key}")
network_key_upper=$(bashio::string.upper "${network_key}")
- if [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_1}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_2}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_3}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_4}" ]; then
+ if [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_1}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_2}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_3}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_4}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_5}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_6}" ]; then
bashio::log.fatal
- bashio::log.fatal "The add-on detected that the Z-Wave network key used"
+ bashio::log.fatal "The app detected that the Z-Wave network key used"
bashio::log.fatal "is from the documented example."
bashio::log.fatal
bashio::log.fatal "Using this key is insecure, because it is publicly"
bashio::log.fatal "listed in the documentation."
bashio::log.fatal
- bashio::log.fatal "Please check the add-on documentation on how to"
+ bashio::log.fatal "Please check the app documentation on how to"
bashio::log.fatal "create your own, secret, \"${key}\" and replace"
bashio::log.fatal "the one you have configured."
bashio::log.fatal
bashio::log.fatal "Click on the \"Documentation\" tab in the Z-Wave JS"
- bashio::log.fatal "add-on panel for more information."
+ bashio::log.fatal "app panel for more information."
bashio::log.fatal
bashio::exit.nok
elif ! bashio::var.has_value "${network_key}"; then
@@ -93,6 +366,8 @@ s0_legacy=$(bashio::config "s0_legacy_key")
s2_access_control=$(bashio::config "s2_access_control_key")
s2_authenticated=$(bashio::config "s2_authenticated_key")
s2_unauthenticated=$(bashio::config "s2_unauthenticated_key")
+lr_s2_access_control=$(bashio::config "lr_s2_access_control_key")
+lr_s2_authenticated=$(bashio::config "lr_s2_authenticated_key")
if ! bashio::config.has_value 'log_level'; then
log_level=$(bashio::info.logging)
@@ -102,6 +377,23 @@ else
log_level=$(bashio::config 'log_level')
fi
+if bashio::config.equals 'rf_region' 'Automatic'; then
+ country=$(bashio::supervisor.country)
+ rf_region="${country_rf_region_map[$country]:-"Default (EU)"}"
+ bashio::log.info "RF region set to Automatic: ${rf_region}"
+else
+ rf_region=$(bashio::config 'rf_region')
+fi
+rf_region_integer=${rf_region_integer_map["${rf_region}"]}
+
+if [[ "${rf_region_integer}" -eq 255 ]]; then
+ rf_json=$(jq -n '{autoPowerlevels: true}')
+ bashio::log.info "Using default RF region settings"
+else
+ rf_json=$(jq -n --argjson region "${rf_region_integer}" '{region: $region, autoPowerlevels: true}')
+ bashio::log.info "Setting RF region to (${rf_region})"
+fi
+
host_chassis=$(bashio::host.chassis)
if bashio::config.equals 'soft_reset' 'Automatic'; then
@@ -133,11 +425,17 @@ fi
if bashio::config.true 'disable_controller_recovery'; then
bashio::log.info "Automatic controller recovery disabled"
- bashio::log.warning "WARNING: If your controller becomes unresponsive, commands may start to fail and nodes may start to get marked as dead until the controller is able to recover on its own. If it doesn't recover on its own, you will need to restart the add-on manually to try to recover yourself."
+ bashio::log.warning "WARNING: If your controller becomes unresponsive, commands may start to fail and nodes may start to get marked as dead until the controller is able to recover on its own. If it doesn't recover on its own, you will need to restart the app manually to try to recover yourself."
# Add NO_CONTROLLER_RECOVERY to presets array
presets_array+=("NO_CONTROLLER_RECOVERY")
fi
+if bashio::config.true 'disable_watchdog'; then
+ bashio::log.info "Hardware watchdog disabled"
+ # Add NO_WATCHDOG to presets array
+ presets_array+=("NO_WATCHDOG")
+fi
+
# Convert presets array to JSON string and add to config
if [[ ${#presets_array[@]} -eq 0 ]]; then
presets="[]"
@@ -154,11 +452,34 @@ bashio::var.json \
s2_access_control "${s2_access_control}" \
s2_authenticated "${s2_authenticated}" \
s2_unauthenticated "${s2_unauthenticated}" \
+ lr_s2_access_control "${lr_s2_access_control}" \
+ lr_s2_authenticated "${lr_s2_authenticated}" \
log_level "${log_level}" \
log_to_file "${log_to_file}" \
log_max_files "${log_max_files}" \
+ rf_json "${rf_json}" \
soft_reset "^${soft_reset}" \
presets "${presets}" |
tempio \
-template /usr/share/tempio/zwave_config.conf \
-out /etc/zwave_config.json
+
+# Create default settings.json in addon config directory if it doesn't exist
+if ! bashio::fs.file_exists "/config/settings.json"; then
+ bashio::log.info "Creating default settings.json..."
+ # Disable MQTT by default
+ mqtt=$(bashio::var.json \
+ disabled "^true" \
+ )
+ # Disable Z-Wave JS UI logs by default
+ gateway=$(bashio::var.json \
+ logEnabled "^false" \
+ logLevel info \
+ logToFile "^false" \
+ )
+
+ bashio::var.json \
+ gateway "^${gateway}" \
+ mqtt "^${mqtt}" \
+ > /config/settings.json
+fi
diff --git a/zwave_js/rootfs/etc/cont-init.d/structure.sh b/zwave_js/rootfs/etc/cont-init.d/structure.sh
index 0e10818768e..2e698f35a5a 100755
--- a/zwave_js/rootfs/etc/cont-init.d/structure.sh
+++ b/zwave_js/rootfs/etc/cont-init.d/structure.sh
@@ -1,4 +1,5 @@
#!/usr/bin/with-contenv bashio
+# shellcheck shell=bash
# ==============================================================================
# Setup folder structure
# ==============================================================================
diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/discovery b/zwave_js/rootfs/etc/services.d/zwave_js/discovery
index a9acd83418f..3303c089dbb 100755
--- a/zwave_js/rootfs/etc/services.d/zwave_js/discovery
+++ b/zwave_js/rootfs/etc/services.d/zwave_js/discovery
@@ -1,4 +1,6 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Send zwave_js discovery information to Home Assistant
# ==============================================================================
diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/finish b/zwave_js/rootfs/etc/services.d/zwave_js/finish
index 5a23d05348c..f18f83626d1 100755
--- a/zwave_js/rootfs/etc/services.d/zwave_js/finish
+++ b/zwave_js/rootfs/etc/services.d/zwave_js/finish
@@ -1,11 +1,12 @@
#!/usr/bin/env bashio
+# vim: ft=bash
# ==============================================================================
# Take down the S6 supervision tree when service fails
# s6-overlay docs: https://github.com/just-containers/s6-overlay
# ==============================================================================
if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then
- bashio::log.warning "Halt add-on"
+ bashio::log.warning "Halt app"
exec /run/s6/basedir/bin/halt
fi
diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/run b/zwave_js/rootfs/etc/services.d/zwave_js/run
index 02a52b5ec41..e5059c18a2f 100755
--- a/zwave_js/rootfs/etc/services.d/zwave_js/run
+++ b/zwave_js/rootfs/etc/services.d/zwave_js/run
@@ -1,19 +1,45 @@
#!/usr/bin/with-contenv bashio
+# vim: ft=bash
+# shellcheck shell=bash
# ==============================================================================
# Start Z-Wave JS service for Z-Wave radio
# ==============================================================================
-SERIAL_DEVICE=$(bashio::config 'device')
-# Emulate serial Hardware for test & development
-if bashio::config.true 'emulate_hardware'; then
- SERIAL_DEVICE="--mock-driver"
+# Get config values
+DEVICE=$(bashio::config 'device')
+SOCKET=$(bashio::config 'socket')
+
+# Filter out null values
+if [[ "${DEVICE}" == "null" ]]; then
+ DEVICE=""
+fi
+if [[ "${SOCKET}" == "null" ]]; then
+ SOCKET=""
+fi
+
+# Determine which to use
+if bashio::var.has_value "${DEVICE}"; then
+ CONNECTION_TYPE="device"
+ SERIAL_DEVICE="${DEVICE}"
+elif bashio::var.has_value "${SOCKET}"; then
+ CONNECTION_TYPE="socket"
+ SERIAL_DEVICE="${SOCKET}"
+else
+ bashio::exit.nok "Either 'device' or 'socket' must be configured"
fi
+bashio::log.info "Using ${CONNECTION_TYPE}: ${SERIAL_DEVICE}"
+
# Send out discovery information to Home Assistant
./discovery &
-# Set external config directory
+# Where Z-Wave JS should extract the config files to
export ZWAVEJS_EXTERNAL_CONFIG=/data/db
+# Externally configure Z-Wave JS UI, removing the fields from settings
+export ZWAVE_PORT=${SERIAL_DEVICE}
+export ZWAVE_EXTERNAL_SETTINGS=/etc/zwave_config.json
+
# Run daemon, passing external config directory in as environment variable
-exec zwave-server ${SERIAL_DEVICE} --config /etc/zwave_config.json --disable-dns-sd
+# shellcheck disable=SC2086
+exec zwave-js-ui
diff --git a/zwave_js/rootfs/usr/share/tempio/zwave_config.conf b/zwave_js/rootfs/usr/share/tempio/zwave_config.conf
index 8ffdff4a689..16adecd83b4 100644
--- a/zwave_js/rootfs/usr/share/tempio/zwave_config.conf
+++ b/zwave_js/rootfs/usr/share/tempio/zwave_config.conf
@@ -1,12 +1,11 @@
{
- "logConfig": {
- "enabled": true,
- "level": "{{ .log_level }}",
- "logToFile": {{ .log_to_file }},
- "maxFiles": {{ .log_max_files }},
- "filename": "/config/zwave",
- "forceConsole": true
- },
+ "logEnabled": true,
+ "logLevel": "{{ .log_level }}",
+ "logToFile": {{ .log_to_file }},
+ "maxFiles": {{ .log_max_files }},
+ "logFilename": "/config/zwave",
+ "forceConsole": true,
+ "rf": {{ .rf_json }},
"storage": {
"cacheDir": "/config/cache",
"throttle": "slow"
@@ -17,6 +16,14 @@
"S2_Authenticated": "{{ .s2_authenticated }}",
"S2_Unauthenticated": "{{ .s2_unauthenticated }}"
},
+ "securityKeysLongRange": {
+ "S2_AccessControl": "{{ .lr_s2_access_control }}",
+ "S2_Authenticated": "{{ .lr_s2_authenticated }}"
+ },
"enableSoftReset": {{ .soft_reset }},
- "presets": {{ .presets }}
+ "presets": {{ .presets }},
+ "serverEnabled": true,
+ "serverPort": 3000,
+ "serverHost": null,
+ "serverServiceDiscoveryDisabled": true
}
diff --git a/zwave_js/translations/en.yaml b/zwave_js/translations/en.yaml
index 47221ddc157..d9f9125525b 100644
--- a/zwave_js/translations/en.yaml
+++ b/zwave_js/translations/en.yaml
@@ -3,11 +3,11 @@ configuration:
device:
name: Device
description: The Z-Wave controller device.
- emulate_hardware:
- name: Enable Emulated Hardware
+ socket:
+ name: Socket
description: >-
- If you don't have a USB stick, you can use a fake stick for testing
- purposes.
+ Instead of using a physical device, you can connect to a Z-Wave adapter
+ via a socket.
log_level:
name: Log Level
description: This option sets the log level of Z-Wave JS.
@@ -25,9 +25,12 @@ configuration:
network_key:
name: Network Key
description: >-
- In previous versions of the addon, this was the only key that was needed.
+ In previous versions of the app, this was the only key that was needed.
With the introduction of S2 security inclusion in zwave-js, this option
has been deprecated.
+ rf_region:
+ name: Radio Frequency Region
+ description: The radio frequency region that the controller should use.
s0_legacy_key:
name: S0 Legacy Key
description: >-
@@ -48,11 +51,21 @@ configuration:
description: >-
This must be provided in order to include devices with the S2
Unauthenticated security class.
+ lr_s2_access_control_key:
+ name: Z-Wave Long Range S2 Access Control Key
+ description: >-
+ This must be provided in order to include devices using Z-Wave
+ Long Range with the S2 Access Control security class.
+ lr_s2_authenticated_key:
+ name: Z-Wave Long Range S2 Authenticated Key
+ description: >-
+ This must be provided in order to include devices using Z-Wave
+ Long Range with the S2 Authenticated security class.
soft_reset:
name: 500 series controller soft-reset
description: >-
- This setting tells the add-on how to handle soft-resets for 500 series
- controllers. The default setting, Automatic, instructs the add-on to
+ This setting tells the app how to handle soft-resets for 500 series
+ controllers. The default setting, Automatic, instructs the app to
automatically detect whether or not this needs to be enabled. The
default setting should work for most users, so only change this setting
if you know what you are doing and/or you are asked to.
@@ -64,9 +77,16 @@ configuration:
recover on its own if it's capable of doing so. While the controller is
unresponsive, commands will start to fail and nodes may randomly get
marked as dead. If a controller is not able to recover on its own, you
- will need to restart the add-on to attempt recovery. In most cases, users
+ will need to restart the app to attempt recovery. In most cases, users
will never need to use this feature, so only change this setting if you
know what you are doing and/or you are asked to.
+ disable_watchdog:
+ name: Disable Z-Wave JS (hardware) watchdog
+ description: >-
+ This setting will prevent Z-Wave JS from enabling the hardware watchdog
+ on supporting controllers. In most cases, users will never need to use
+ this feature, so only change this setting if you know what you are doing
+ and/or you are asked to.
safe_mode:
name: Enable safe mode
description: >-
@@ -77,4 +97,5 @@ configuration:
change this setting if you know what you are doing and/or you are asked
to.
network:
- 3000/tcp: Z-Wave JS communication
+ 3000/tcp: Z-Wave JS WebSocket communication port
+ 8091/tcp: Z-Wave JS UI web port