Compare commits

...

14 Commits

Author SHA1 Message Date
Claude
08c5aaffe0 birdnet-go: resolve MariaDB host to IPv4 before connecting
On HAOS >=17.3 the Supervisor network gained IPv6, but the MariaDB addon
only grants the service user from the IPv4 subnet. Connecting via IPv6
causes auth failure and makes CREATE DATABASE appear to lack privileges.
Mirror the fix from the photoprism addon: resolve via getent ahostsv4
and add --skip-ssl. Password remains in MYSQL_PWD env var (safer than
--password= on the CLI).
2026-06-23 09:10:30 +00:00
Claude
675bd199d4 birdnet-go: fall back to existence-check when CREATE DATABASE is denied
The HA MariaDB service user may lack global CREATE DATABASE privilege. If
CREATE DATABASE fails, check whether the database was pre-created manually
and proceed if so. Only exit 1 if the database is truly absent, with a
clear instruction to create it manually.
2026-06-23 09:05:16 +00:00
Claude
97c165b59a birdnet-go: guard SQLite revert to only run when HA MariaDB host matches
When mariadb_auto_config is disabled, only revert output.mysql.enabled to
false (and re-enable SQLite) if config.yaml's output.mysql.host matches the
HA MariaDB service host. This prevents clobbering a manually-configured
MySQL block pointing at a different server on every addon restart.
2026-06-23 08:55:39 +00:00
Alexandre
6d3b19dbac nobuild 2026-06-23 10:52:08 +02:00
Claude
51088a4eac birdnet-go: redact MariaDB password from addon logs 2026-06-23 08:48:26 +00:00
Claude
c56cbfcbea birdnet-go: fix MariaDB auto-config database creation and SQLite revert
- Create the `birdnet` database before connecting: birdnet-go's MySQL
  driver connects to an existing schema and fails with "database doesn't
  exist" if the schema was never created. The init script now issues
  CREATE DATABASE IF NOT EXISTS via the mysql CLI before writing
  config.yaml, fixing first-use failures (discussion #2912).
- Revert to SQLite when mariadb_auto_config is disabled: previously
  disabling the option only logged a hint; now it also sets
  output.mysql.enabled = false and output.sqlite.enabled = true so
  turning the option off fully undoes the MariaDB wiring.
- Add mariadb-client to PACKAGES so the mysql CLI is available inside
  the container.
2026-06-23 08:29:04 +00:00
Alexandre
618be6731e nobuild 2026-06-22 20:51:45 +02:00
Alexandre
bd25b567a9 Merge pull request #2791 from alexbelgium/dependabot/github_actions/actions/checkout-7
Bump actions/checkout from 6 to 7
2026-06-22 20:15:08 +02:00
dependabot[bot]
181743e157 Bump actions/checkout from 6 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-22 18:02:32 +00:00
Alexandre
e1d8f0bb6a Update README.md 2026-06-22 08:35:54 +02:00
Alexandre
6d0b014ee9 Update HAINTEGRATION.md 2026-06-22 08:34:54 +02:00
Alexandre
2ccc1945bc nobuild 2026-06-22 08:34:23 +02:00
Alexandre
06ee00a495 Update CHANGELOG.md 2026-06-22 08:33:19 +02:00
Alexandre
dbbbdd3581 Update 33-mqtt.sh 2026-06-22 08:32:45 +02:00
19 changed files with 123 additions and 35 deletions

View File

@@ -13,7 +13,7 @@ jobs:
container: ghcr.io/hadolint/hadolint:latest-alpine
steps:
- name: ↩️ Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Get changed files
id: changed_files
@@ -34,7 +34,7 @@ jobs:
container: koalaman/shellcheck-alpine:latest
steps:
- name: ↩️ Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Get changed files
id: changed_files
@@ -54,7 +54,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: ↩️ Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
# Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install jq + yq (v4)
run: |

View File

@@ -9,7 +9,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install apps
run: |
git pull --rebase origin master

View File

@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -82,7 +82,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Assign issues
run: |
# Init

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Ping mapped submitter when add-on is mentioned
env:

View File

@@ -18,7 +18,7 @@ jobs:
changedChangelogFiles: ${{ steps.changed-files.outputs.changelogs_files }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Find changed addon directories
id: find_addons
run: |
@@ -72,7 +72,7 @@ jobs:
addon: ${{ fromJSON(needs.check-addon-changes.outputs.changedAddons) }}
steps:
- name: ↩️ Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: 🔎 Run Home Assistant Add-on Lint
uses: frenck/action-addon-linter@v2
@@ -90,7 +90,7 @@ jobs:
addon: ${{ fromJSON(needs.check-addon-changes.outputs.changedAddons) }}
steps:
- name: ↩️ Checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: ℹ️ Gather addon info
id: information

View File

@@ -22,7 +22,7 @@ jobs:
changedAddons: ${{ steps.find_addons.outputs.changed_addons }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -56,7 +56,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -108,7 +108,7 @@ jobs:
matrix:
addon: ${{ fromJSON(needs.detect-changed-addons.outputs.changedAddons) }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Run Home Assistant Add-on Lint
uses: frenck/action-addon-linter@v2
with:
@@ -133,7 +133,7 @@ jobs:
- arch: aarch64
runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
persist-credentials: false
@@ -331,7 +331,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -402,7 +402,7 @@ jobs:
contents: write
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository contents
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Use action to check for CRLF endings
uses: erclu/check-crlf@v1
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest # Use a Linux runner
steps:
- name: Checkout repository contents
uses: actions/checkout@v6 # Use the checkout action
uses: actions/checkout@v7 # Use the checkout action
- name: Find files with CRLF endings
uses: erclu/check-crlf@v1.2.0 # Use the check-crlf action
id: check-crlf # Assign an id to this step

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Compress Images
id: calibre

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Create stats
run: |
echo "Starting"

View File

@@ -1,4 +1,13 @@
## nightly-20260615-2 (2026-06-23)
- MariaDB auto-config: resolve MariaDB hostname to IPv4 before connecting — on HAOS >=17.3 the Supervisor network gained IPv6 but the MariaDB addon only grants the service user from the IPv4 subnet, causing authentication failures and `CREATE DATABASE` errors; also add `--skip-ssl` to match the connection approach used by other addons
- MariaDB auto-config: disabling `mariadb_auto_config` now reverts to SQLite only when `output.mysql.host` in config.yaml matches the HA MariaDB host (avoids clobbering manually-configured MySQL pointing at a different server)
- Added `mariadb-client` to the addon packages so the `mysql` CLI used for database creation is available inside the container
- MQTT auto-config now also enables BirdNET-Go's native Home Assistant MQTT auto-discovery: detection sensors appear in Home Assistant automatically with no manual YAML (existing UI/config.yaml edits are preserved)
- MQTT auto-config seeds `realtime.mqtt.retain: true` (only when unset) so sensor states survive Home Assistant restarts
- Added supervisor watchdog (tcp://[HOST]:[PORT:8080]) so the add-on is automatically restarted if BirdNET-Go stops responding
- Added backup_exclude for rotated logs, making Home Assistant backups smaller (SQLite journals are kept so hot backups stay consistent)
## nightly-20260615 (2026-06-17)
- Update to latest version from tphakala/birdnet-go (changelog : https://github.com/tphakala/birdnet-go/releases)
## nightly-20260601-2 (03-06-2026)

View File

@@ -62,7 +62,7 @@ COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES="alsa-utils libasound2-plugins nginx yq"
ENV PACKAGES="alsa-utils libasound2-plugins mariadb-client nginx yq"
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh

View File

@@ -2,6 +2,15 @@
BirdNET-Go can be integrated with Home Assistant using a MQTT Broker.
> **💡 Easiest path — automatic discovery.** If you run the Home Assistant
> Mosquitto (MQTT) addon, just set `mqtt_auto_config: true` in this add-on's
> options. The add-on then wires in the broker credentials **and** enables
> BirdNET-Go's native Home Assistant MQTT auto-discovery, so the detection
> sensors appear in Home Assistant automatically with **no manual YAML at
> all**. The manual sensor/template/card configuration below is only needed if
> you want to build your own custom entities instead of (or in addition to) the
> auto-discovered ones.
## MQTT Configuration
Your Home Assistant must be setup with MQTT and BirdNET-Go MQTT integration must be enabled. Modify the BirdNET-Go config.yaml file to enable MQTT. If you are using the Mosquitto Broker addon, you will see a log message during the BirdNET-Go startup showing the internal MQTT server details needed for configuration similar to below.

View File

@@ -64,7 +64,7 @@ Additional environment variables can be configured there
### MQTT and MariaDB auto-configuration (opt-in)
If the Home Assistant **MQTT** addon is installed and running and you set `mqtt_auto_config: true` in the addon options, the addon writes the HA Mosquitto credentials directly into BirdNET-Go's `config.yaml` on every startup: `realtime.mqtt.enabled`, `broker`, `username`, and `password` are populated, and the topic defaults to `birdnet`. When the option is `false` (the default), the addon still logs the broker details and reminds you about the option whenever Mosquitto is detected — nothing is written.
If the Home Assistant **MQTT** addon is installed and running and you set `mqtt_auto_config: true` in the addon options, the addon writes the HA Mosquitto credentials directly into BirdNET-Go's `config.yaml` on every startup: `realtime.mqtt.enabled`, `broker`, `username`, and `password` are populated, and the topic defaults to `birdnet`. In addition, it enables BirdNET-Go's **native Home Assistant MQTT auto-discovery** (`realtime.mqtt.homeassistant.enabled`), so the detection sensors show up in Home Assistant automatically — **no manual MQTT sensor YAML required** (the hand-written sensors in [HAINTEGRATION.md](./HAINTEGRATION.md) remain available if you prefer to build your own). Messages are also retained (`realtime.mqtt.retain: true`) so sensor states survive Home Assistant restarts. When the option is `false` (the default), the addon still logs the broker details and reminds you about the option whenever Mosquitto is detected — nothing is written.
If the Home Assistant **MariaDB** addon is installed and running and you set `mariadb_auto_config: true`, the addon writes the HA credentials into `output.mysql.*` and sets `output.sqlite.enabled` to `false` (database name `birdnet`, created on first connect). When the option is `false` (the default), the addon only logs the credentials so you can configure them manually.

View File

@@ -2,6 +2,8 @@ arch:
- aarch64
- amd64
audio: true
backup_exclude:
- logs/**
description: Realtime BirdNET and Battybirdnet soundscape analyzer
devices:
- /dev/dri
@@ -126,4 +128,5 @@ slug: birdnet-go
udev: true
url: https://github.com/alexbelgium/hassio-addons/tree/master/birdnet-go
usb: true
version: "nightly-20260615"
version: "nightly-20260615-2"
video: true

View File

@@ -6,8 +6,17 @@ set -e
# credentials directly into BirdNET-Go's config.yaml. Upstream reads MySQL
# settings only from YAML (no env-var overrides exist), so this is the only
# way to auto-configure them. The behaviour is opt-in via the
# mariadb_auto_config addon option. When the option is off but MariaDB is
# detected, we log a one-shot hint pointing users at the option.
# mariadb_auto_config addon option.
#
# When the option is off but MariaDB is detected, we log a one-shot hint and
# ensure config.yaml falls back to SQLite (reverting any previously written
# mysql block). This is safe because BirdNET-Go's config.yaml defaults to
# SQLite and the mysql block is only ever written by this script.
#
# When the option is on we:
# 1. Create the "birdnet" database if it does not already exist — birdnet-go
# connects to an existing schema and does not create it automatically.
# 2. Write the MySQL credentials into config.yaml and disable SQLite.
CONFIG_LOCATION="/config/config.yaml"
MYSQL_DATABASE="birdnet"
@@ -23,13 +32,27 @@ MYSQL_PASS="$(bashio::services 'mysql' 'password')"
if ! bashio::config.true 'mariadb_auto_config'; then
bashio::log.green "---"
bashio::log.yellow "Home Assistant MariaDB addon detected. Set 'mariadb_auto_config: true' in the addon options to wire it into BirdNET-Go automatically (and disable SQLite). Connection details:"
bashio::log.yellow "Home Assistant MariaDB addon detected but mariadb_auto_config is disabled; ensuring BirdNET-Go uses SQLite."
bashio::log.yellow "Set 'mariadb_auto_config: true' in the addon options to wire MariaDB into BirdNET-Go automatically. Connection details:"
bashio::log.blue "Database user : ${MYSQL_USER}"
bashio::log.blue "Database password: ${MYSQL_PASS}"
bashio::log.blue "Database password: [redacted]"
bashio::log.blue "Database name : ${MYSQL_DATABASE}"
bashio::log.blue "Host-name : ${MYSQL_HOST}"
bashio::log.blue "Port : ${MYSQL_PORT}"
bashio::log.green "---"
if [ -f "$CONFIG_LOCATION" ]; then
# Only revert if config.yaml points at the HA MariaDB host we would have
# written — a mysql block pointing at a different host was set manually.
# shellcheck disable=SC2016
CURRENT_MYSQL_HOST="$(yq -r '.output.mysql.host // empty' "$CONFIG_LOCATION" 2>/dev/null || true)"
if yq -e '.output.mysql.enabled == true' "$CONFIG_LOCATION" >/dev/null 2>&1 \
&& [ "${CURRENT_MYSQL_HOST}" = "${MYSQL_HOST}" ]; then
yq -i -y \
'.output.mysql.enabled = false
| .output.sqlite.enabled = true' \
"$CONFIG_LOCATION"
fi
fi
exit 0
fi
@@ -39,12 +62,36 @@ if [ ! -f "$CONFIG_LOCATION" ]; then
fi
bashio::log.green "---"
bashio::log.blue "mariadb_auto_config enabled; writing Home Assistant MariaDB credentials into BirdNET-Go config and disabling SQLite"
bashio::log.blue "mariadb_auto_config enabled; creating MariaDB database and wiring credentials into BirdNET-Go config"
bashio::log.blue "Host: ${MYSQL_HOST}:${MYSQL_PORT}"
bashio::log.blue "User: ${MYSQL_USER}"
bashio::log.blue "Database: ${MYSQL_DATABASE} (will be created by BirdNET-Go on first connect)"
bashio::log.blue "Database: ${MYSQL_DATABASE}"
bashio::log.green "---"
# Resolve MariaDB hostname to IPv4: on HAOS >=17.3 the Supervisor network
# gained IPv6, but the MariaDB addon only grants its user from the IPv4
# subnet. Fall back to the raw hostname if resolution fails.
MYSQL_HOST_RESOLVED="$(getent ahostsv4 "${MYSQL_HOST}" 2>/dev/null | awk '{print $1; exit}')"
MYSQL_HOST_RESOLVED="${MYSQL_HOST_RESOLVED:-${MYSQL_HOST}}"
if [ "${MYSQL_HOST_RESOLVED}" != "${MYSQL_HOST}" ]; then
bashio::log.blue "Resolved ${MYSQL_HOST} -> ${MYSQL_HOST_RESOLVED} (forcing IPv4)"
fi
# Create the database — birdnet-go connects to an existing schema and does NOT
# create it automatically. MYSQL_PWD avoids exposing the password via the
# process command line.
if ! MYSQL_PWD="${MYSQL_PASS}" mysql \
--skip-ssl \
--host="${MYSQL_HOST_RESOLVED}" \
--port="${MYSQL_PORT}" \
--user="${MYSQL_USER}" \
--connect-timeout=10 \
-e "CREATE DATABASE IF NOT EXISTS \`${MYSQL_DATABASE}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"; then
bashio::log.error "Failed to create MariaDB database '${MYSQL_DATABASE}' — verify the MariaDB addon is running and the user has CREATE DATABASE privileges"
exit 1
fi
bashio::log.blue "Database '${MYSQL_DATABASE}' is ready"
# Upstream config.go stores port as a string; pass it as such to match.
# $host / $port / etc. are jq/yq variables, not shell expansions — the
# single quotes around the filter are intentional.

View File

@@ -8,6 +8,11 @@ set -e
# way to auto-configure them. The behaviour is opt-in via the
# mqtt_auto_config addon option. When the option is off but Mosquitto is
# detected, we log a one-shot hint pointing users at the option.
#
# In addition to the broker credentials we enable BirdNET-Go's native Home
# Assistant MQTT auto-discovery (realtime.mqtt.homeassistant.*). This makes
# the detection sensors appear in Home Assistant automatically, so users no
# longer have to hand-write the MQTT sensor YAML from HAINTEGRATION.md.
CONFIG_LOCATION="/config/config.yaml"
@@ -23,7 +28,7 @@ MQTT_BROKER="tcp://${MQTT_HOST}:${MQTT_PORT}"
if ! bashio::config.true 'mqtt_auto_config'; then
bashio::log.green "---"
bashio::log.yellow "Home Assistant MQTT addon detected. Set 'mqtt_auto_config: true' in the addon options to wire it into BirdNET-Go automatically. Connection details:"
bashio::log.yellow "Home Assistant MQTT addon detected. Set 'mqtt_auto_config: true' in the addon options to wire it into BirdNET-Go automatically AND enable Home Assistant auto-discovery (sensors appear in HA with no manual YAML). Connection details:"
bashio::log.blue "MQTT user : ${MQTT_USER}"
bashio::log.blue "MQTT password: ${MQTT_PASS}"
bashio::log.blue "MQTT broker : ${MQTT_BROKER}"
@@ -40,10 +45,21 @@ bashio::log.green "---"
bashio::log.blue "mqtt_auto_config enabled; writing Home Assistant MQTT credentials into BirdNET-Go config"
bashio::log.blue "Broker: ${MQTT_BROKER}"
bashio::log.blue "User: ${MQTT_USER}"
bashio::log.blue "Home Assistant auto-discovery: enabled (sensors appear in HA automatically)"
bashio::log.green "---"
# $broker / $user / $pass / "birdnet" are jq/yq variables and literals,
# not shell expansions, so the single quotes are intentional.
#
# Connection fields (enabled/broker/username/password) are force-set on every
# start so they track the HA MQTT addon's rotating credentials. Topic and the
# homeassistant.* discovery knobs use "//=" so they are only seeded when
# missing. retain is seeded via an explicit has() check rather than "//=",
# because jq treats a user-set "retain: false" as falsy and "//=" would wrongly
# flip it back to true; has() seeds the default only when the key is truly
# absent. Any value the user later changes in the BirdNET-Go UI or config.yaml
# therefore survives restarts. homeassistant.enabled is force-set to true
# because turning on discovery is the whole point of the auto-config option.
# shellcheck disable=SC2016
yq -i -y \
--arg broker "$MQTT_BROKER" \
@@ -53,5 +69,9 @@ yq -i -y \
| .realtime.mqtt.broker = $broker
| .realtime.mqtt.username = $user
| .realtime.mqtt.password = $pass
| .realtime.mqtt.topic //= "birdnet"' \
| .realtime.mqtt.topic //= "birdnet"
| (if (.realtime.mqtt | has("retain")) then . else .realtime.mqtt.retain = true end)
| .realtime.mqtt.homeassistant.enabled = true
| .realtime.mqtt.homeassistant.discovery_prefix //= "homeassistant"
| .realtime.mqtt.homeassistant.device_name //= "BirdNET-Go"' \
"$CONFIG_LOCATION"