mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-07-06 05:58:47 +02:00
Merge pull request #2742 from alexbelgium/claude/birdnet-homeassistant-review-T5oI4
birdnet-go: harden config init, auto-wire MQTT/MariaDB, trim ingress …
This commit is contained in:
@@ -1,3 +1,14 @@
|
|||||||
|
## nightly-20260525-3 (28-05-2026)
|
||||||
|
- New `mqtt_auto_config` addon option (default `false`). When `true` and the Home Assistant MQTT addon is active, `realtime.mqtt.{enabled,broker,username,password}` are written directly to `config.yaml` on every restart. When `false` but Mosquitto is detected, the addon still logs the broker details and reminds you about the option — nothing is written.
|
||||||
|
- New `mariadb_auto_config` addon option (default `false`). When `true` and the Home Assistant MariaDB addon is active, `output.mysql.*` is filled in and `output.sqlite.enabled` is set to `false`. When `false` but MariaDB is detected, the addon logs the credentials and reminds you about the option.
|
||||||
|
- **Breaking**: `output.sqlite.path` and `logging.file_output.*` are now seeded only when missing from `config.yaml` (previously overwritten every restart). Values changed through the BirdNET-Go UI or by hand-editing `config.yaml` now survive container restarts. If you relied on `LOG_MAX_SIZE_MB` / `LOG_MAX_AGE_DAYS` addon options to override an existing setting in `config.yaml`, remove the existing key from `config.yaml` or edit it directly — the option will only be applied on first run.
|
||||||
|
- **Breaking (UI only)**: The nginx ingress reverse-proxy no longer rewrites HTML `href`/`src`/`action` attributes; upstream BirdNET-Go handles those itself via `X-Ingress-Path`. JavaScript string-literal rewrites are unchanged. Please file an issue if you see broken images, links, or forms in the ingress UI after upgrade.
|
||||||
|
- Fix database-migration restore: the timestamped backup created during a `BIRDSONGS_FOLDER` change was being written to the script's working directory and looked up under a fresh timestamp on restore, so a SQL failure left the user unable to recover. Backup path is now absolute and reused for restore.
|
||||||
|
- Harden the `BIRDSONGS_FOLDER` SQL/YAML path substitution: paths containing characters outside `[A-Za-z0-9._/-]` are now rejected up front instead of being interpolated raw into the SQL UPDATE statement.
|
||||||
|
- Tolerate a missing internet connection on first boot: if the default `config.yaml` cannot be downloaded from GitHub, the init script now seeds an empty YAML document so the addon-defaults block populates a usable config (rather than aborting the script on the next `yq` call under `set -e`).
|
||||||
|
- Warn (without failing the build) if the upstream `entrypoint.sh` patch target drifts in a new nightly.
|
||||||
|
- Remove a dead nginx upstream definition that pointed at an unused port.
|
||||||
|
|
||||||
## nightly-20260525-2 (26-05-2026)
|
## nightly-20260525-2 (26-05-2026)
|
||||||
- Suppress noisy startup logs: silence `chmod /dev/snd` errors on the read-only HA mount, and hide unavailable ALSA plugins (JACK, OSS, dsnoop) from device enumeration so libjack and pcm_oss/dsnoop probes no longer print at launch. ALSA overrides are written to `/root/.asoundrc` (since `/etc/asound.conf` is read-only in this environment).
|
- Suppress noisy startup logs: silence `chmod /dev/snd` errors on the read-only HA mount, and hide unavailable ALSA plugins (JACK, OSS, dsnoop) from device enumeration so libjack and pcm_oss/dsnoop probes no longer print at launch. ALSA overrides are written to `/root/.asoundrc` (since `/etc/asound.conf` is read-only in this environment).
|
||||||
- Allow advanced users to override the ALSA config by dropping a custom `asound.conf` into the addon config folder.
|
- Allow advanced users to override the ALSA config by dropping a custom `asound.conf` into the addon config folder.
|
||||||
|
|||||||
@@ -39,8 +39,14 @@ RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -e
|
|||||||
# Silence "chmod: Read-only file system" noise from upstream entrypoint:
|
# Silence "chmod: Read-only file system" noise from upstream entrypoint:
|
||||||
# Home Assistant mounts /dev/snd read-only, so the chmod is a no-op and the
|
# Home Assistant mounts /dev/snd read-only, so the chmod is a no-op and the
|
||||||
# stderr output is just noise. The "|| true" already absorbs the exit code.
|
# stderr output is just noise. The "|| true" already absorbs the exit code.
|
||||||
|
# Warn (without failing the build) if the upstream pattern drifts so we notice
|
||||||
|
# in CI logs and can update the patch.
|
||||||
RUN if [ -f /usr/bin/entrypoint.sh ]; then \
|
RUN if [ -f /usr/bin/entrypoint.sh ]; then \
|
||||||
sed -i 's#chmod -R a+rw /dev/snd || true#chmod -R a+rw /dev/snd 2>/dev/null || true#' /usr/bin/entrypoint.sh; \
|
if grep -q 'chmod -R a+rw /dev/snd || true' /usr/bin/entrypoint.sh; then \
|
||||||
|
sed -i 's#chmod -R a+rw /dev/snd || true#chmod -R a+rw /dev/snd 2>/dev/null || true#' /usr/bin/entrypoint.sh; \
|
||||||
|
else \
|
||||||
|
echo "WARN: upstream entrypoint.sh /dev/snd chmod pattern not found; nightly drift?" >&2; \
|
||||||
|
fi; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Uses /bin for compatibility purposes
|
# Uses /bin for compatibility purposes
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ Options can be configured through three ways :
|
|||||||
ALSA_CARD : number of the card (0 or 1 usually), see https://github.com/tphakala/birdnet-go/blob/main/doc/installation.md#deciding-alsa_card-value
|
ALSA_CARD : number of the card (0 or 1 usually), see https://github.com/tphakala/birdnet-go/blob/main/doc/installation.md#deciding-alsa_card-value
|
||||||
TZ: Etc/UTC specify a timezone to use, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
TZ: Etc/UTC specify a timezone to use, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||||
COMMAND : realtime --rtsp url # allows to provide arguments to birdnet-go
|
COMMAND : realtime --rtsp url # allows to provide arguments to birdnet-go
|
||||||
|
mqtt_auto_config: false # set true to auto-wire the Home Assistant MQTT addon into config.yaml
|
||||||
|
mariadb_auto_config: false # set true to auto-wire the Home Assistant MariaDB addon into config.yaml (also disables SQLite)
|
||||||
```
|
```
|
||||||
|
|
||||||
- Config.yaml
|
- Config.yaml
|
||||||
@@ -57,6 +59,14 @@ Additional variables can be configured using the config.yaml file found in /conf
|
|||||||
- Config_env.yaml
|
- Config_env.yaml
|
||||||
Additional environment variables can be configured there
|
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 **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.
|
||||||
|
|
||||||
|
The addon also seeds `output.sqlite.path` and `logging.file_output.*` defaults only when those keys are missing from `config.yaml`, so values you change through the BirdNET-Go UI now survive container restarts.
|
||||||
|
|
||||||
### Mounting Drives
|
### Mounting Drives
|
||||||
|
|
||||||
This addon supports mounting both local drives and remote SMB shares:
|
This addon supports mounting both local drives and remote SMB shares:
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ options:
|
|||||||
LOG_MAX_SIZE_MB: 50
|
LOG_MAX_SIZE_MB: 50
|
||||||
LOG_MAX_AGE_DAYS: 7
|
LOG_MAX_AGE_DAYS: 7
|
||||||
homeassistant_microphone: false
|
homeassistant_microphone: false
|
||||||
|
mqtt_auto_config: false
|
||||||
|
mariadb_auto_config: false
|
||||||
panel_admin: false
|
panel_admin: false
|
||||||
panel_icon: mdi:bird
|
panel_icon: mdi:bird
|
||||||
ports:
|
ports:
|
||||||
@@ -114,6 +116,8 @@ schema:
|
|||||||
cifsusername: str?
|
cifsusername: str?
|
||||||
homeassistant_microphone: bool?
|
homeassistant_microphone: bool?
|
||||||
localdisks: str?
|
localdisks: str?
|
||||||
|
mariadb_auto_config: bool?
|
||||||
|
mqtt_auto_config: bool?
|
||||||
networkdisks: str?
|
networkdisks: str?
|
||||||
services:
|
services:
|
||||||
- mysql:want
|
- mysql:want
|
||||||
@@ -122,4 +126,4 @@ slug: birdnet-go
|
|||||||
udev: true
|
udev: true
|
||||||
url: https://github.com/alexbelgium/hassio-addons/tree/master/birdnet-go
|
url: https://github.com/alexbelgium/hassio-addons/tree/master/birdnet-go
|
||||||
usb: true
|
usb: true
|
||||||
version: "nightly-20260525-2"
|
version: "nightly-20260525-3"
|
||||||
|
|||||||
@@ -3,12 +3,41 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Default Variables
|
# Default Variables
|
||||||
DEFAULT_BIRDSONGS_FOLDER="/data/clips/"
|
DEFAULT_BIRDSONGS_FOLDER="/data/clips"
|
||||||
CONFIG_LOCATION="/config/config.yaml"
|
CONFIG_LOCATION="/config/config.yaml"
|
||||||
|
|
||||||
|
# Strip trailing slashes; canonical internal form has none.
|
||||||
|
normalize_path() {
|
||||||
|
local p="$1"
|
||||||
|
while [[ "$p" == */ && "$p" != "/" ]]; do
|
||||||
|
p="${p%/}"
|
||||||
|
done
|
||||||
|
printf '%s' "$p"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reject paths containing characters that would break the SQL/YAML literals
|
||||||
|
# we substitute into below. We deliberately allow only "safe" filename chars.
|
||||||
|
validate_safe_path() {
|
||||||
|
local p="$1"
|
||||||
|
if [[ ! "$p" =~ ^[A-Za-z0-9._/-]+$ ]]; then
|
||||||
|
bashio::log.fatal "Refusing unsafe path: '$p' (only [A-Za-z0-9._/-] allowed)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [ ! -f "$CONFIG_LOCATION" ]; then
|
if [ ! -f "$CONFIG_LOCATION" ]; then
|
||||||
bashio::log.warning "There is no config.yaml yet in the config folder, downloading a default one. Please customize"
|
bashio::log.warning "There is no config.yaml yet in the config folder, downloading a default one. Please customize"
|
||||||
curl -L -s -S https://raw.githubusercontent.com/tphakala/birdnet-go/refs/heads/main/internal/conf/config.yaml -o "$CONFIG_LOCATION"
|
# Network may be unreachable on first boot. If the download fails, seed
|
||||||
|
# an empty YAML document so the yq reads/writes below succeed and the
|
||||||
|
# default-value seeding logic later in this script populates a usable
|
||||||
|
# config. (We can't remove the file and continue — subsequent yq calls
|
||||||
|
# under set -e would abort the init script.)
|
||||||
|
if ! curl -fL -s -S \
|
||||||
|
https://raw.githubusercontent.com/tphakala/birdnet-go/refs/heads/main/internal/conf/config.yaml \
|
||||||
|
-o "$CONFIG_LOCATION"; then
|
||||||
|
bashio::log.warning "Could not download default config.yaml; seeding an empty document so addon defaults can populate it"
|
||||||
|
echo '{}' > "$CONFIG_LOCATION"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#################
|
#################
|
||||||
@@ -22,20 +51,24 @@ fi
|
|||||||
######################
|
######################
|
||||||
# Birdsongs Location
|
# Birdsongs Location
|
||||||
######################
|
######################
|
||||||
CURRENT_BIRDSONGS_FOLDER="clips/"
|
# Read the current folder from config.yaml; "// """ collapses both missing
|
||||||
# Read the current folder from config files
|
# keys and explicit nulls (e.g. in a freshly seeded "{}" doc) to an empty
|
||||||
CURRENT_BIRDSONGS_FOLDER="$(yq '.realtime.audio.export.path' "$CONFIG_LOCATION" | tr -d '\"')"
|
# string so the ${VAR:-DEFAULT} fallback below kicks in.
|
||||||
|
CURRENT_BIRDSONGS_FOLDER="$(yq -r '.realtime.audio.export.path // ""' "$CONFIG_LOCATION")"
|
||||||
CURRENT_BIRDSONGS_FOLDER="${CURRENT_BIRDSONGS_FOLDER:-$DEFAULT_BIRDSONGS_FOLDER}"
|
CURRENT_BIRDSONGS_FOLDER="${CURRENT_BIRDSONGS_FOLDER:-$DEFAULT_BIRDSONGS_FOLDER}"
|
||||||
|
# Treat the upstream-shipped relative "clips/" as the legacy default.
|
||||||
# Adjust default path if it matches the default string
|
if [[ "$CURRENT_BIRDSONGS_FOLDER" == "clips" || "$CURRENT_BIRDSONGS_FOLDER" == "clips/" ]]; then
|
||||||
if [[ "$CURRENT_BIRDSONGS_FOLDER" == "clips/" ]]; then
|
|
||||||
CURRENT_BIRDSONGS_FOLDER="$DEFAULT_BIRDSONGS_FOLDER"
|
CURRENT_BIRDSONGS_FOLDER="$DEFAULT_BIRDSONGS_FOLDER"
|
||||||
fi
|
fi
|
||||||
|
CURRENT_BIRDSONGS_FOLDER="$(normalize_path "$CURRENT_BIRDSONGS_FOLDER")"
|
||||||
|
|
||||||
# Set the new birdsongs folder
|
# Set the new birdsongs folder from addon options (default: relative "clips").
|
||||||
BIRDSONGS_FOLDER="$(bashio::config "BIRDSONGS_FOLDER")"
|
BIRDSONGS_FOLDER="$(bashio::config "BIRDSONGS_FOLDER")"
|
||||||
BIRDSONGS_FOLDER="${BIRDSONGS_FOLDER:-clips/}"
|
BIRDSONGS_FOLDER="$(normalize_path "${BIRDSONGS_FOLDER:-clips}")"
|
||||||
BIRDSONGS_FOLDER="${BIRDSONGS_FOLDER%/}" # Remove trailing slash if present
|
|
||||||
|
validate_safe_path "$BIRDSONGS_FOLDER"
|
||||||
|
validate_safe_path "$CURRENT_BIRDSONGS_FOLDER"
|
||||||
|
|
||||||
if [[ ! "$BIRDSONGS_FOLDER" == /* ]]; then
|
if [[ ! "$BIRDSONGS_FOLDER" == /* ]]; then
|
||||||
if [ ! -d "/config/$BIRDSONGS_FOLDER" ]; then
|
if [ ! -d "/config/$BIRDSONGS_FOLDER" ]; then
|
||||||
mkdir -p "/config/$BIRDSONGS_FOLDER"
|
mkdir -p "/config/$BIRDSONGS_FOLDER"
|
||||||
@@ -52,42 +85,43 @@ fi
|
|||||||
bashio::log.info "... audio clips saved to $BIRDSONGS_FOLDER according to addon options"
|
bashio::log.info "... audio clips saved to $BIRDSONGS_FOLDER according to addon options"
|
||||||
|
|
||||||
# Migrate data if the folder has changed
|
# Migrate data if the folder has changed
|
||||||
if [[ "${CURRENT_BIRDSONGS_FOLDER%/}" != "${BIRDSONGS_FOLDER%/}" ]]; then
|
if [[ "$CURRENT_BIRDSONGS_FOLDER" != "$BIRDSONGS_FOLDER" ]]; then
|
||||||
bashio::log.warning "Birdsongs folder changed from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER"
|
bashio::log.warning "Birdsongs folder changed from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER"
|
||||||
# Update config files with the new birdsongs folder path
|
# Update config.yaml with the new birdsongs folder path (trailing slash
|
||||||
yq -i -y ".realtime.audio.export.path = \"$BIRDSONGS_FOLDER/\"" "$CONFIG_LOCATION"
|
# restored only at the boundary, since birdnet-go expects it).
|
||||||
|
yq -i -y ".realtime.audio.export.path = \"${BIRDSONGS_FOLDER}/\"" "$CONFIG_LOCATION"
|
||||||
# Move files only if sqlite paths changed
|
# Move files only if sqlite paths changed
|
||||||
if [[ -d "$CURRENT_BIRDSONGS_FOLDER" && "$(ls -A "$CURRENT_BIRDSONGS_FOLDER")" ]]; then
|
if [[ -d "$CURRENT_BIRDSONGS_FOLDER" && "$(ls -A "$CURRENT_BIRDSONGS_FOLDER")" ]]; then
|
||||||
bashio::log.warning "Migrating files from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER"
|
bashio::log.warning "Migrating files from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER"
|
||||||
cp -rnf "$CURRENT_BIRDSONGS_FOLDER"/* "$BIRDSONGS_FOLDER"/
|
cp -rnf "$CURRENT_BIRDSONGS_FOLDER"/* "$BIRDSONGS_FOLDER"/
|
||||||
mv "${CURRENT_BIRDSONGS_FOLDER%/}" "${CURRENT_BIRDSONGS_FOLDER%/}_migrated"
|
mv "$CURRENT_BIRDSONGS_FOLDER" "${CURRENT_BIRDSONGS_FOLDER}_migrated"
|
||||||
fi
|
fi
|
||||||
# Adapt the database
|
# Adapt the database
|
||||||
if [ -f /config/birdnet.db ]; then
|
if [ -f /config/birdnet.db ]; then
|
||||||
# Prepare
|
|
||||||
backup="$(date +%Y%m%d_%H%M%S)"
|
backup="$(date +%Y%m%d_%H%M%S)"
|
||||||
bashio::log.warning "Modifying database paths from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER. A backup named birdnet.db_$backup will be created before"
|
BACKUP_FILE="/config/birdnet.db_${backup}"
|
||||||
|
bashio::log.warning "Modifying database paths from $CURRENT_BIRDSONGS_FOLDER to $BIRDSONGS_FOLDER. A backup will be created at ${BACKUP_FILE}"
|
||||||
|
|
||||||
# Create backup
|
# Create backup at the absolute path we'll restore from on failure.
|
||||||
if ! cp /config/birdnet.db "birdnet.db_$backup"; then
|
if ! cp /config/birdnet.db "$BACKUP_FILE"; then
|
||||||
bashio::log.error "Failed to create a backup of the database. Aborting path modification."
|
bashio::log.error "Failed to create a backup of the database. Aborting path modification."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Execute the query using sqlite3
|
# Paths were validated above against [A-Za-z0-9._/-]+ so quote
|
||||||
SQL_QUERY="UPDATE notes SET clip_name = '${BIRDSONGS_FOLDER%/}/' || substr(clip_name, length('${CURRENT_BIRDSONGS_FOLDER%/}/') + 1) WHERE clip_name LIKE '${CURRENT_BIRDSONGS_FOLDER%/}/%';"
|
# escaping in the SQL literal is not a concern.
|
||||||
|
SQL_QUERY="UPDATE notes SET clip_name = '${BIRDSONGS_FOLDER}/' || substr(clip_name, length('${CURRENT_BIRDSONGS_FOLDER}/') + 1) WHERE clip_name LIKE '${CURRENT_BIRDSONGS_FOLDER}/%';"
|
||||||
|
|
||||||
if ! sqlite3 /config/birdnet.db "$SQL_QUERY"; then
|
if ! sqlite3 /config/birdnet.db "$SQL_QUERY"; then
|
||||||
bashio::log.warning "An error occurred while updating the paths. The database backup will be restored."
|
bashio::log.warning "An error occurred while updating the paths. The database backup will be restored."
|
||||||
BACKUP_FILE="/config/birdnet.db_$(date +%Y%m%d_%H%M%S)" # Make sure this matches the earlier backup filename
|
|
||||||
if [ -f "$BACKUP_FILE" ]; then
|
if [ -f "$BACKUP_FILE" ]; then
|
||||||
mv "$BACKUP_FILE" /config/birdnet.db
|
mv "$BACKUP_FILE" /config/birdnet.db
|
||||||
bashio::log.info "The database backup has been restored."
|
bashio::log.info "The database backup has been restored."
|
||||||
else
|
else
|
||||||
bashio::log.error "Backup file not found! Manual intervention required."
|
bashio::log.error "Backup file $BACKUP_FILE not found! Manual intervention required."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Paths have been successfully updated."
|
bashio::log.info "Paths have been successfully updated."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -95,11 +129,13 @@ fi
|
|||||||
####################
|
####################
|
||||||
# Correct Defaults
|
# Correct Defaults
|
||||||
####################
|
####################
|
||||||
bashio::log.info "Correcting configuration for defaults"
|
# Seed addon-specific defaults only if the user has not set them in
|
||||||
|
# config.yaml. The "//=" form leaves any user-edited value alone, so
|
||||||
|
# changes made via the BirdNET-Go UI or by hand-editing /config/config.yaml
|
||||||
|
# survive container restarts.
|
||||||
|
bashio::log.info "Seeding default configuration values (only if missing)"
|
||||||
|
|
||||||
# Update database location in config files
|
yq -i -y '.output.sqlite.path //= "/config/birdnet.db"' "$CONFIG_LOCATION"
|
||||||
yq -i -y ".output.sqlite.path = \"/config/birdnet.db\"" "$CONFIG_LOCATION"
|
|
||||||
bashio::log.info "... database is located in /config/birdnet.db"
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Log Management
|
# Log Management
|
||||||
@@ -109,13 +145,13 @@ LOG_MAX_SIZE_MB="${LOG_MAX_SIZE_MB:-50}"
|
|||||||
LOG_MAX_AGE_DAYS="$(bashio::config "LOG_MAX_AGE_DAYS")"
|
LOG_MAX_AGE_DAYS="$(bashio::config "LOG_MAX_AGE_DAYS")"
|
||||||
LOG_MAX_AGE_DAYS="${LOG_MAX_AGE_DAYS:-7}"
|
LOG_MAX_AGE_DAYS="${LOG_MAX_AGE_DAYS:-7}"
|
||||||
|
|
||||||
bashio::log.info "Configuring log rotation: max ${LOG_MAX_SIZE_MB}MB per file, max ${LOG_MAX_AGE_DAYS} days retention"
|
bashio::log.info "Seeding default log rotation: max ${LOG_MAX_SIZE_MB}MB per file, max ${LOG_MAX_AGE_DAYS} days retention (only applied if not already set)"
|
||||||
|
|
||||||
# Configure log rotation in birdnet-go config
|
# Seed log-rotation defaults; do not clobber user-edited values.
|
||||||
yq -i -y ".logging.file_output.max_size = ${LOG_MAX_SIZE_MB}" "$CONFIG_LOCATION"
|
yq -i -y ".logging.file_output.max_size //= ${LOG_MAX_SIZE_MB}" "$CONFIG_LOCATION"
|
||||||
yq -i -y ".logging.file_output.max_age = ${LOG_MAX_AGE_DAYS}" "$CONFIG_LOCATION"
|
yq -i -y ".logging.file_output.max_age //= ${LOG_MAX_AGE_DAYS}" "$CONFIG_LOCATION"
|
||||||
yq -i -y ".logging.file_output.max_rotated_files = 3" "$CONFIG_LOCATION"
|
yq -i -y '.logging.file_output.max_rotated_files //= 3' "$CONFIG_LOCATION"
|
||||||
yq -i -y ".logging.file_output.compress = true" "$CONFIG_LOCATION"
|
yq -i -y '.logging.file_output.compress //= true' "$CONFIG_LOCATION"
|
||||||
|
|
||||||
# Trim existing log files that exceed the configured max age
|
# Trim existing log files that exceed the configured max age
|
||||||
LOG_DIR="/config/logs"
|
LOG_DIR="/config/logs"
|
||||||
|
|||||||
@@ -2,15 +2,64 @@
|
|||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Gives mariadb information
|
# When the Home Assistant MariaDB addon is active, optionally wire its
|
||||||
|
# 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.
|
||||||
|
|
||||||
if bashio::services.available 'mysql'; then
|
CONFIG_LOCATION="/config/config.yaml"
|
||||||
bashio::log.green "---"
|
MYSQL_DATABASE="birdnet"
|
||||||
bashio::log.yellow "MariaDB addon is active on your system! If you want to use it instead of sqlite, here are the informations to encode :"
|
|
||||||
bashio::log.blue "Database user : $(bashio::services "mysql" "username")"
|
if ! bashio::services.available 'mysql'; then
|
||||||
bashio::log.blue "Database password : $(bashio::services "mysql" "password")"
|
exit 0
|
||||||
bashio::log.blue "Database name : birdnet"
|
|
||||||
bashio::log.blue "Host-name : $(bashio::services "mysql" "host")"
|
|
||||||
bashio::log.blue "Port : $(bashio::services "mysql" "port")"
|
|
||||||
bashio::log.green "---"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MYSQL_HOST="$(bashio::services 'mysql' 'host')"
|
||||||
|
MYSQL_PORT="$(bashio::services 'mysql' 'port')"
|
||||||
|
MYSQL_USER="$(bashio::services 'mysql' 'username')"
|
||||||
|
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.blue "Database user : ${MYSQL_USER}"
|
||||||
|
bashio::log.blue "Database password: ${MYSQL_PASS}"
|
||||||
|
bashio::log.blue "Database name : ${MYSQL_DATABASE}"
|
||||||
|
bashio::log.blue "Host-name : ${MYSQL_HOST}"
|
||||||
|
bashio::log.blue "Port : ${MYSQL_PORT}"
|
||||||
|
bashio::log.green "---"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_LOCATION" ]; then
|
||||||
|
bashio::log.warning "Skipping MariaDB auto-configuration: $CONFIG_LOCATION not found"
|
||||||
|
exit 0
|
||||||
|
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 "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.green "---"
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
yq -i -y \
|
||||||
|
--arg host "$MYSQL_HOST" \
|
||||||
|
--arg port "$MYSQL_PORT" \
|
||||||
|
--arg user "$MYSQL_USER" \
|
||||||
|
--arg pass "$MYSQL_PASS" \
|
||||||
|
--arg db "$MYSQL_DATABASE" \
|
||||||
|
'.output.mysql.enabled = true
|
||||||
|
| .output.mysql.host = $host
|
||||||
|
| .output.mysql.port = $port
|
||||||
|
| .output.mysql.username = $user
|
||||||
|
| .output.mysql.password = $pass
|
||||||
|
| .output.mysql.database = $db
|
||||||
|
| .output.sqlite.enabled = false' \
|
||||||
|
"$CONFIG_LOCATION"
|
||||||
|
|||||||
@@ -2,13 +2,56 @@
|
|||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Gives mqtt information
|
# When the Home Assistant MQTT addon is active, optionally wire its
|
||||||
|
# credentials directly into BirdNET-Go's config.yaml. Upstream reads MQTT
|
||||||
|
# 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
|
||||||
|
# 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.
|
||||||
|
|
||||||
if bashio::services.available 'mqtt'; then
|
CONFIG_LOCATION="/config/config.yaml"
|
||||||
bashio::log.green "---"
|
|
||||||
bashio::log.yellow "MQTT addon is active on your system! Add the MQTT details below to the Birdnet-go config.yaml :"
|
if ! bashio::services.available 'mqtt'; then
|
||||||
bashio::log.blue "MQTT user : $(bashio::services "mqtt" "username")"
|
exit 0
|
||||||
bashio::log.blue "MQTT password : $(bashio::services "mqtt" "password")"
|
|
||||||
bashio::log.blue "MQTT broker : tcp://$(bashio::services "mqtt" "host"):$(bashio::services "mqtt" "port")"
|
|
||||||
bashio::log.green "---"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MQTT_HOST="$(bashio::services 'mqtt' 'host')"
|
||||||
|
MQTT_PORT="$(bashio::services 'mqtt' 'port')"
|
||||||
|
MQTT_USER="$(bashio::services 'mqtt' 'username')"
|
||||||
|
MQTT_PASS="$(bashio::services 'mqtt' 'password')"
|
||||||
|
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.blue "MQTT user : ${MQTT_USER}"
|
||||||
|
bashio::log.blue "MQTT password: ${MQTT_PASS}"
|
||||||
|
bashio::log.blue "MQTT broker : ${MQTT_BROKER}"
|
||||||
|
bashio::log.green "---"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_LOCATION" ]; then
|
||||||
|
bashio::log.warning "Skipping MQTT auto-configuration: $CONFIG_LOCATION not found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
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.green "---"
|
||||||
|
|
||||||
|
# $broker / $user / $pass / "birdnet" are jq/yq variables and literals,
|
||||||
|
# not shell expansions, so the single quotes are intentional.
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
yq -i -y \
|
||||||
|
--arg broker "$MQTT_BROKER" \
|
||||||
|
--arg user "$MQTT_USER" \
|
||||||
|
--arg pass "$MQTT_PASS" \
|
||||||
|
'.realtime.mqtt.enabled = true
|
||||||
|
| .realtime.mqtt.broker = $broker
|
||||||
|
| .realtime.mqtt.username = $user
|
||||||
|
| .realtime.mqtt.password = $pass
|
||||||
|
| .realtime.mqtt.topic //= "birdnet"' \
|
||||||
|
"$CONFIG_LOCATION"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
upstream backend {
|
|
||||||
server 127.0.0.1:8096;
|
|
||||||
}
|
|
||||||
@@ -76,7 +76,6 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
include /etc/nginx/includes/resolver.conf;
|
include /etc/nginx/includes/resolver.conf;
|
||||||
include /etc/nginx/includes/upstream.conf;
|
|
||||||
|
|
||||||
include /etc/nginx/servers/*.conf;
|
include /etc/nginx/servers/*.conf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,29 +21,25 @@ server {
|
|||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
# Tell BirdNET-Go its proxy prefix (NEW — required)
|
# Tell BirdNET-Go its proxy prefix. Upstream honours X-Ingress-Path
|
||||||
|
# in internal/api/server.go and rewrites HTML href/src/action
|
||||||
|
# attributes itself, so we no longer duplicate that work here.
|
||||||
proxy_set_header X-Ingress-Path %%ingress_entry%%;
|
proxy_set_header X-Ingress-Path %%ingress_entry%%;
|
||||||
|
|
||||||
# Prevent timeouts
|
# Prevent timeouts
|
||||||
proxy_read_timeout 86400;
|
proxy_read_timeout 86400;
|
||||||
proxy_send_timeout 86400;
|
proxy_send_timeout 86400;
|
||||||
|
|
||||||
# sub_filter setup
|
# sub_filter setup: keep gzip off and the type filter wide so JS gets
|
||||||
|
# touched too (the upstream HTML rewriter does not look inside JS).
|
||||||
proxy_set_header Accept-Encoding "";
|
proxy_set_header Accept-Encoding "";
|
||||||
sub_filter_once off;
|
sub_filter_once off;
|
||||||
sub_filter_types *;
|
sub_filter_types *;
|
||||||
|
|
||||||
# HTML attribute rewrites
|
# JS string-literal rewrites — paths embedded in JS code are not
|
||||||
sub_filter href=\"/ href=\"%%ingress_entry%%/;
|
# touched by upstream's HTML rewriter, so we patch them here.
|
||||||
sub_filter src=\"/ src=\"%%ingress_entry%%/;
|
|
||||||
sub_filter src=\"'/ src=\"'%%ingress_entry%%/;
|
|
||||||
sub_filter action=\"/ action=\"%%ingress_entry%%/;
|
|
||||||
|
|
||||||
# JavaScript string rewrites (needed for Vite dynamic imports)
|
|
||||||
sub_filter EventSource('/ EventSource('%%ingress_entry%%/;
|
sub_filter EventSource('/ EventSource('%%ingress_entry%%/;
|
||||||
sub_filter fetch('/ fetch('%%ingress_entry%%/;
|
sub_filter fetch('/ fetch('%%ingress_entry%%/;
|
||||||
|
|
||||||
# Backtick template literal rewrites
|
|
||||||
sub_filter `/api/v `%%ingress_entry%%/api/v;
|
sub_filter `/api/v `%%ingress_entry%%/api/v;
|
||||||
sub_filter "'/api/v" "'%%ingress_entry%%/api/v";
|
sub_filter "'/api/v" "'%%ingress_entry%%/api/v";
|
||||||
sub_filter \"/api/v \"%%ingress_entry%%/api/v;
|
sub_filter \"/api/v \"%%ingress_entry%%/api/v;
|
||||||
@@ -53,8 +49,6 @@ server {
|
|||||||
sub_filter `/asset `%%ingress_entry%%/asset;
|
sub_filter `/asset `%%ingress_entry%%/asset;
|
||||||
sub_filter "'/asset" "'%%ingress_entry%%/asset";
|
sub_filter "'/asset" "'%%ingress_entry%%/asset";
|
||||||
sub_filter \"/asset \"%%ingress_entry%%/asset;
|
sub_filter \"/asset \"%%ingress_entry%%/asset;
|
||||||
|
|
||||||
# Streaming/EventSource fix
|
|
||||||
sub_filter window.location.origin} window.location.origin}%%ingress_entry%%;
|
sub_filter window.location.origin} window.location.origin}%%ingress_entry%%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user