Compare commits

..

6 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
ed59a7140d fix: guard addon config symlink creation 2026-06-03 06:19:02 +00:00
copilot-swe-agent[bot]
a158621de9 refactor: simplify addon config symlink setup 2026-06-03 06:18:23 +00:00
copilot-swe-agent[bot]
c95c53eb63 fix: harden addon config migration 2026-06-03 06:17:39 +00:00
copilot-swe-agent[bot]
d9b525b464 fix: address filebrowser quantum review feedback 2026-06-03 06:17:00 +00:00
copilot-swe-agent[bot]
b48899b5bf Fix FileBrowser Quantum database migration path to use correct addon_configs directory
The migration code was checking `/homeassistant/addons_config/filebrowser_quantum/`
but the actual HA addon config path is `/homeassistant/addon_configs/db21ed7f_filebrowser_quantum/`.

Changes:
- Add migration check for the correct addon_configs path with slug prefix
- Handle the standard `addon_configs` directory for symlink operations
- Keep legacy `addons_config` path support for backward compatibility

Fixes: Configuration doesn't survive over restarts
2026-06-03 05:19:00 +00:00
copilot-swe-agent[bot]
830c6cebec Initial plan 2026-06-03 05:13:10 +00:00
5 changed files with 217 additions and 58 deletions

View File

@@ -1,7 +1,3 @@
## 1.3.3-8 (03-06-2026)
- Minor bugs fixed
## 1.3.3-7 (03-06-2026)
- Allow config persistence
## 1.3.3 (2026-05-19)
- Update to latest version from gtsteffaniak/filebrowser (changelog : https://github.com/gtsteffaniak/filebrowser/releases)

View File

@@ -52,7 +52,7 @@ RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_auto
# Manual apps
ENV PACKAGES="bind-tools \
nginx \
python3 yq"
python3"
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh
@@ -71,8 +71,7 @@ RUN chmod 777 /ha_entrypoint.sh
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
RUN sed -i "s|/command/with-contenv|/usr/bin/env|g" "/ha_entrypoint.sh" && \
[[ -f /etc/cont-init.d/01-config_yaml.sh ]] && rm -r /etc/cont-init.d/01-config_yaml.sh
RUN sed -i "s|/command/with-contenv|/usr/bin/env|g" "/ha_entrypoint.sh"
VOLUME [ "/data" ]
WORKDIR /

View File

@@ -73,8 +73,6 @@ devices:
- /dev/md3
environment:
FB_BASEURL: /filebrowser_quantum
FILEBROWSER_CONFIG: "/config/config.yaml"
FILEBROWSER_DATABASE: "/config/database.db"
PGID: "0"
PUID: "0"
image: ghcr.io/alexbelgium/filebrowser_quantum-{arch}
@@ -112,4 +110,4 @@ schema:
slug: filebrowser_quantum
udev: true
url: https://github.com/alexbelgium/hassio-addons
version: "1.3.3-8"
version: "1.3.3"

View File

@@ -0,0 +1,63 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -e
####################
# Migrate database #
####################
if [ -f /homeassistant/addons_config/filebrowser_quantum/filebrowser_quantum.db ]; then
echo "Moving database from legacy addons_config location to /config"
cp -rnf /homeassistant/addons_config/filebrowser_quantum/* /config/
rm -r /homeassistant/addons_config/filebrowser_quantum
fi
if [ ! -f /config/filebrowser_quantum.db ] && [ -d /addon_configs ]; then
shopt -s nullglob
for addon_config_dir in /addon_configs/*_filebrowser_quantum; do
if [ -f "$addon_config_dir/filebrowser_quantum.db" ]; then
echo "Moving database from addon_configs location to /config"
cp -rnf "$addon_config_dir"/. /config/
break
fi
done
shopt -u nullglob
fi
######################
# Link addon folders #
######################
# Clean symlinks
find /config -maxdepth 1 -type l -delete
if [ -d /homeassistant/addons_config ]; then
find /homeassistant/addons_config -maxdepth 1 -type l -delete
fi
# Remove erroneous folders
if [ -d /homeassistant ]; then
if [ -d /config/addons_config ]; then
rm -r /config/addons_config
fi
if [ -d /config/addon_configs ]; then
rm -r /config/addon_configs
fi
if [ -d /config/addons_autoscripts ]; then
rm -r /config/addons_autoscripts
fi
fi
# Create symlinks with legacy folders
addon_configs_symlink_dir=""
if [ -d /homeassistant/addons_config ]; then
ln -s /homeassistant/addons_config /config
addon_configs_symlink_dir="/config/addons_config"
elif [ -d /addon_configs ]; then
mkdir -p /config/addon_configs
addon_configs_symlink_dir="/config/addon_configs"
fi
if [ -n "$addon_configs_symlink_dir" ] && [ -d /addon_configs ]; then
find /addon_configs/ -maxdepth 1 -mindepth 1 -type d -not -name "*filebrowser_quantum*" -exec ln -s {} "$addon_configs_symlink_dir"/ \;
fi
if [ -d /homeassistant/addons_autoscripts ]; then
ln -s /homeassistant/addons_autoscripts /config
fi

View File

@@ -65,60 +65,163 @@ mkdir -p /var/log/nginx && touch /var/log/nginx/error.log
# FILEBROWSER CONFIGURATION #
############################
CONFIG_PATH="/config/filebrowser_quantum.yaml"
mkdir -p /config /cache
# Copy default config if not existing
if [ ! -f "$FILEBROWSER_CONFIG" ]; then
cp /home/filebrowser/data/config.yaml "$FILEBROWSER_CONFIG"
fi
export FILEBROWSER_CONFIG="${CONFIG_PATH}"
bashio::log.info "Updating FileBrowser config..."
python3 - <<'PY'
import json
import os
# --- Server (hardcoded values) ---
bashio::log.info "... set server"
yq e -i ".server.port = 8080" "$FILEBROWSER_CONFIG"
yq e -i ".server.listen = \"0.0.0.0\"" "$FILEBROWSER_CONFIG"
yq e -i ".server.database = \"/config/database.db\"" "$FILEBROWSER_CONFIG"
yq e -i ".server.cacheDir = \"/cache\"" "$FILEBROWSER_CONFIG"
yq e -i ".server.source.path = \"/\"" "$FILEBROWSER_CONFIG"
options_path = "/data/options.json"
config_path = os.environ["FILEBROWSER_CONFIG"]
# --- Base URL (from env or config) ---
bashio::log.info "... set base URL to allow ingress"
BASE_URL=$(bashio::config 'base_url' "${FB_BASEURL:-/}")
yq e -i ".server.baseURL = \"${BASE_URL}\"" "$FILEBROWSER_CONFIG"
with open(options_path, "r", encoding="utf-8") as f:
options = json.load(f)
# --- Auth method ---
AUTH_METHOD=$(bashio::config 'auth_method' 'password')
bashio::log.info "... authentication method set to $AUTH_METHOD"
case "$AUTH_METHOD" in
noauth)
yq e -i ".auth.methods.noauth = true" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.password.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.proxy.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.oidc.enabled = false" "$FILEBROWSER_CONFIG"
;;
password)
yq e -i ".auth.methods.noauth = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.password.enabled = true" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.proxy.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.oidc.enabled = false" "$FILEBROWSER_CONFIG"
;;
proxy)
yq e -i ".auth.methods.noauth = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.password.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.proxy.enabled = true" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.oidc.enabled = false" "$FILEBROWSER_CONFIG"
;;
oidc)
yq e -i ".auth.methods.noauth = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.password.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.proxy.enabled = false" "$FILEBROWSER_CONFIG"
yq e -i ".auth.methods.oidc.enabled = true" "$FILEBROWSER_CONFIG"
;;
*)
bashio::log.fatal "Unknown auth_method: $AUTH_METHOD"
;;
esac
base_url = options.get("base_url") or os.environ.get("FB_BASEURL") or "/"
def bool_or_none(value):
return value if isinstance(value, bool) else None
sources = []
for source in options.get("sources") or [{"path": "/", "name": "Root", "default_enabled": True}]:
entry = {"path": source.get("path", "/")}
if source.get("name"):
entry["name"] = source["name"]
source_config = {}
config_mappings = {
"default_enabled": "defaultEnabled",
"default_user_scope": "defaultUserScope",
"create_user_dir": "createUserDir",
"disable_indexing": "disableIndexing",
"deny_by_default": "denyByDefault",
"private": "private",
"indexing_interval_minutes": "indexingIntervalMinutes",
}
for option_key, config_key in config_mappings.items():
if option_key in source and source[option_key] not in (None, ""):
value = source[option_key]
if option_key == "indexing_interval_minutes" and not value:
continue
source_config[config_key] = value
conditionals = {}
if "ignore_hidden" in source:
value = bool_or_none(source.get("ignore_hidden"))
if value is not None:
conditionals["ignoreHidden"] = value
if "ignore_zero_size_folders" in source:
value = bool_or_none(source.get("ignore_zero_size_folders"))
if value is not None:
conditionals["ignoreZeroSizeFolders"] = value
if conditionals:
source_config["conditionals"] = conditionals
if source_config:
entry["config"] = source_config
sources.append(entry)
server = {
"port": 8080,
"listen": "0.0.0.0",
"baseURL": base_url,
"logging": [
{
"levels": options.get("log_levels", "info|warning|error"),
}
],
"database": "/config/filebrowser_quantum.db",
"cacheDir": "/cache",
"cacheDirCleanup": options.get("cache_dir_cleanup", True),
"disablePreviews": options.get("disable_previews", False),
"disablePreviewResize": options.get("disable_preview_resize", False),
"disableTypeDetectionByHeader": options.get("disable_type_detection_by_header", False),
"disableUpdateCheck": options.get("disable_update_check", False),
"sources": sources,
}
if options.get("external_url"):
server["externalUrl"] = options["external_url"]
if options.get("internal_url"):
server["internalUrl"] = options["internal_url"]
if options.get("max_archive_size_gb"):
server["maxArchiveSize"] = options["max_archive_size_gb"]
certfile = os.environ.get("CERTFILE")
keyfile = os.environ.get("KEYFILE")
if certfile and keyfile:
server["tlsCert"] = certfile
server["tlsKey"] = keyfile
auth_method = options.get("auth_method", "password")
password_config = {
"enabled": auth_method == "password",
"minLength": options.get("password_min_length", 5),
"signup": options.get("password_signup", False),
"enforcedOtp": options.get("password_enforced_otp", False),
}
proxy_config = {
"enabled": auth_method == "proxy",
}
if options.get("proxy_auth_header"):
proxy_config["header"] = options["proxy_auth_header"]
proxy_config["createUser"] = options.get("proxy_auth_create_user", False)
if options.get("proxy_auth_logout_redirect_url"):
proxy_config["logoutRedirectUrl"] = options["proxy_auth_logout_redirect_url"]
oidc_config = {
"enabled": auth_method == "oidc",
}
if options.get("oidc_client_id"):
oidc_config["clientId"] = options["oidc_client_id"]
if options.get("oidc_client_secret"):
oidc_config["clientSecret"] = options["oidc_client_secret"]
if options.get("oidc_issuer_url"):
oidc_config["issuerUrl"] = options["oidc_issuer_url"]
if options.get("oidc_scopes"):
oidc_config["scopes"] = options["oidc_scopes"]
if options.get("oidc_user_identifier"):
oidc_config["userIdentifier"] = options["oidc_user_identifier"]
if options.get("oidc_admin_group"):
oidc_config["adminGroup"] = options["oidc_admin_group"]
if options.get("oidc_groups_claim"):
oidc_config["groupsClaim"] = options["oidc_groups_claim"]
if options.get("oidc_logout_redirect_url"):
oidc_config["logoutRedirectUrl"] = options["oidc_logout_redirect_url"]
oidc_config["createUser"] = options.get("oidc_create_user", False)
oidc_config["disableVerifyTLS"] = options.get("oidc_disable_verify_tls", False)
auth = {
"tokenExpirationHours": options.get("token_expiration_hours", 2),
"adminUsername": options.get("admin_username", "admin"),
"adminPassword": options.get("admin_password", "admin"),
"methods": {
"noauth": auth_method == "noauth",
"password": password_config,
"proxy": proxy_config,
"oidc": oidc_config,
},
}
frontend = {
"name": "FileBrowser Quantum",
}
config = {
"server": server,
"auth": auth,
"frontend": frontend,
}
with open(config_path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=2)
f.write("\n")
PY
######################
# LAUNCH FILEBROWSER #