From 951342005124b571ab991cdfab691e37802e3c04 Mon Sep 17 00:00:00 2001 From: Alexandre <44178713+alexbelgium@users.noreply.github.com> Date: Mon, 6 Jul 2026 07:44:05 +0200 Subject: [PATCH] Add Manyfold public hostname option --- manyfold/CHANGELOG.md | 3 +++ manyfold/config.yaml | 5 +++- manyfold/run.sh | 44 +++++++++++++++++++++++++++++++++++ manyfold/translations/en.yaml | 3 +++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/manyfold/CHANGELOG.md b/manyfold/CHANGELOG.md index 07d2180f44..ba70726feb 100644 --- a/manyfold/CHANGELOG.md +++ b/manyfold/CHANGELOG.md @@ -1,4 +1,7 @@ +## 0.146.1 (2026-07-06) +- Add configurable Manyfold public hostname with Home Assistant external URL and homeassistant.local fallbacks. + ## 0.146.0 (2026-07-04) - Update to latest version from manyfold3d/manyfold (changelog : https://github.com/manyfold3d/manyfold/releases) ## 0.145.1 (24-06-2026) diff --git a/manyfold/config.yaml b/manyfold/config.yaml index 60478d5086..e90c152647 100644 --- a/manyfold/config.yaml +++ b/manyfold/config.yaml @@ -1,7 +1,7 @@ name: "Manyfold" slug: manyfold description: "Manyfold 3D model manager as a Home Assistant add-on, using the upstream image with configurable library/index paths." -version: "0.146.0" +version: "0.146.1" url: "https://github.com/alexbelgium/hassio-addons/tree/master/manyfold" image: ghcr.io/alexbelgium/manyfold-{arch} arch: @@ -9,6 +9,7 @@ arch: - aarch64 startup: services init: false +hassio_api: true ports: 3214/tcp: 3214 @@ -27,6 +28,7 @@ options: puid: 1000 pgid: 1000 multiuser: true + public_hostname: "" library_path: "/share/manyfold/models" thumbnails_path: "/config/thumbnails" log_level: "info" @@ -41,6 +43,7 @@ schema: secret_key_base: str puid: int pgid: int + public_hostname: str? multiuser: bool library_path: str thumbnails_path: str diff --git a/manyfold/run.sh b/manyfold/run.sh index 2508043f73..dbc2bd1418 100755 --- a/manyfold/run.sh +++ b/manyfold/run.sh @@ -14,6 +14,7 @@ DEFAULT_DEFAULT_WORKER_CONCURRENCY="4" DEFAULT_PERFORMANCE_WORKER_CONCURRENCY="1" DEFAULT_MAX_FILE_UPLOAD_SIZE="1073741824" DEFAULT_MAX_FILE_EXTRACT_SIZE="1073741824" +DEFAULT_PUBLIC_HOSTNAME="homeassistant.local" log() { echo "[manyfold-addon] $*" @@ -29,6 +30,40 @@ read_opt() { jq -er --arg k "$key" '.[$k]' "$OPTIONS_JSON" 2>/dev/null || true } +strip_hostname() { + local raw="$1" + + raw="${raw#http://}" + raw="${raw#https://}" + raw="${raw%%/*}" + raw="${raw%%:*}" + + printf '%s\n' "$raw" +} + +detect_ha_public_hostname() { + local supervisor_url="${SUPERVISOR:-http://supervisor}" + local response external_url external_host + + if [[ -z "${SUPERVISOR_TOKEN:-}" ]] || ! command -v curl >/dev/null 2>&1; then + printf '%s\n' "$DEFAULT_PUBLIC_HOSTNAME" + return + fi + + response="$(curl -fsSL \ + -H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \ + "${supervisor_url}/core/api/config" 2>/dev/null || true)" + external_url="$(jq -er '.external_url // empty' <<< "$response" 2>/dev/null || true)" + external_host="$(strip_hostname "$external_url")" + + if [[ -n "$external_host" && "$external_host" != "null" ]]; then + printf '%s\n' "$external_host" + return + fi + + printf '%s\n' "$DEFAULT_PUBLIC_HOSTNAME" +} + normalize_path() { local raw="$1" if command -v realpath >/dev/null 2>&1; then @@ -176,6 +211,7 @@ PERFORMANCE_WORKER_CONCURRENCY="$(read_opt performance_worker_concurrency)"; PER MAX_FILE_UPLOAD_SIZE="$(read_opt max_file_upload_size)"; MAX_FILE_UPLOAD_SIZE="${MAX_FILE_UPLOAD_SIZE:-$DEFAULT_MAX_FILE_UPLOAD_SIZE}" MAX_FILE_EXTRACT_SIZE="$(read_opt max_file_extract_size)"; MAX_FILE_EXTRACT_SIZE="${MAX_FILE_EXTRACT_SIZE:-$DEFAULT_MAX_FILE_EXTRACT_SIZE}" SECRET_KEY_BASE="$(read_opt secret_key_base)"; SECRET_KEY_BASE="${SECRET_KEY_BASE:-}" +PUBLIC_HOSTNAME_RAW="$(read_opt public_hostname)"; PUBLIC_HOSTNAME_RAW="${PUBLIC_HOSTNAME_RAW:-}" [[ "$PUID" =~ ^[0-9]+$ ]] || die "puid must be a non-negative integer" [[ "$PGID" =~ ^[0-9]+$ ]] || die "pgid must be a non-negative integer" @@ -189,6 +225,13 @@ SECRET_KEY_BASE="$(read_opt secret_key_base)"; SECRET_KEY_BASE="${SECRET_KEY_BAS LIBRARY_PATH="$(require_mapped_path "library_path" "$LIBRARY_PATH_RAW")" THUMBNAILS_PATH="$(require_mapped_path "thumbnails_path" "$THUMBNAILS_PATH_RAW")" +if [[ -n "$PUBLIC_HOSTNAME_RAW" ]]; then + PUBLIC_HOSTNAME="$(strip_hostname "$PUBLIC_HOSTNAME_RAW")" +else + PUBLIC_HOSTNAME="$(detect_ha_public_hostname)" +fi +[[ -n "$PUBLIC_HOSTNAME" && "$PUBLIC_HOSTNAME" != "null" ]] || PUBLIC_HOSTNAME="$DEFAULT_PUBLIC_HOSTNAME" + case "$THUMBNAILS_PATH" in /config|/config/*) ;; *) die "thumbnails_path must resolve under /config for persistence" ;; @@ -223,6 +266,7 @@ export MULTIUSER export MANYFOLD_MULTIUSER="$MULTIUSER" export MANYFOLD_LIBRARY_PATH="$LIBRARY_PATH" export MANYFOLD_THUMBNAILS_PATH="$THUMBNAILS_PATH" +export PUBLIC_HOSTNAME export RAILS_LOG_LEVEL="$LOG_LEVEL" export MANYFOLD_LOG_LEVEL="$LOG_LEVEL" export WEB_CONCURRENCY diff --git a/manyfold/translations/en.yaml b/manyfold/translations/en.yaml index e5c2069f6e..f28e2adb8d 100644 --- a/manyfold/translations/en.yaml +++ b/manyfold/translations/en.yaml @@ -11,6 +11,9 @@ configuration: multiuser: name: Multiuser mode description: Enable or disable Manyfold multiuser login. + public_hostname: + name: Public hostname + description: Public hostname used by Manyfold for generated links. Leave blank to use Home Assistant external URL host, or homeassistant.local if unavailable. library_path: name: Library path description: Folder scanned/indexed by Manyfold. Must be under /share, /media, or /config.