diff --git a/.github/scripts/resolve_symlinks.sh b/.github/scripts/resolve_symlinks.sh
new file mode 100755
index 0000000000..4b66a2462d
--- /dev/null
+++ b/.github/scripts/resolve_symlinks.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+# Replace every symlink in the checked-out repository with a real copy of its target.
+#
+# Add-ons share files by symlinking across add-on directories (e.g. webtop/rootfs ->
+# ../webtop_kde/rootfs, and files inside it -> ../../../../claude_desktop/rootfs/...). A
+# Docker build context is a single add-on directory, so any symlink that escapes it has to be
+# materialised before the build.
+#
+# The loop repeats because resolving one symlink can create others: copying a directory
+# symlink with `cp -a` preserves the symlinks *inside* it, and those copies are not part of
+# the file list the current pass is iterating over. Repeating until a pass finds nothing makes
+# the result independent of the order `find` happens to return.
+set -euo pipefail
+
+for _ in 1 2 3 4 5; do
+ mapfile -t links < <(find . -type l)
+ if [ "${#links[@]}" -eq 0 ]; then
+ exit 0
+ fi
+
+ for link in "${links[@]}"; do
+ target=$(readlink -f "$link" || true)
+ if [ -z "$target" ] || [ ! -e "$target" ]; then
+ # Fail rather than drop it. A broken link here means an add-on is missing a file
+ # it expects to ship; silently removing it produces an image that builds fine and
+ # misbehaves at runtime, which is far harder to diagnose than a red build.
+ echo "::error::Broken symlink: $link -> $(readlink "$link")"
+ exit 1
+ fi
+
+ rm "$link"
+ if [ -d "$target" ]; then
+ mkdir -p "$link"
+ cp -a "$target/." "$link/"
+ else
+ cp "$target" "$link"
+ fi
+ done
+done
+
+if [ -n "$(find . -type l)" ]; then
+ echo "::error::Symlinks still present after 5 resolution passes; possible symlink cycle"
+ find . -type l
+ exit 1
+fi
diff --git a/.github/workflows/onpr_check-pr.yaml b/.github/workflows/onpr_check-pr.yaml
index 4635f2070d..accfc91bcf 100644
--- a/.github/workflows/onpr_check-pr.yaml
+++ b/.github/workflows/onpr_check-pr.yaml
@@ -108,6 +108,9 @@ jobs:
- name: ↩️ Checkout
uses: actions/checkout@v7.0.1
+ - name: Resolve symlinks in repository copy
+ run: bash .github/scripts/resolve_symlinks.sh
+
- name: Copy templates into addon build context
env:
ADDON: ${{ matrix.addon }}
diff --git a/.github/workflows/onpush_builder.yaml b/.github/workflows/onpush_builder.yaml
index f9a6b32b94..134ce45d2d 100644
--- a/.github/workflows/onpush_builder.yaml
+++ b/.github/workflows/onpush_builder.yaml
@@ -142,24 +142,7 @@ jobs:
persist-credentials: false
- name: Resolve symlinks in repository copy
- run: |
- set -euo pipefail
-
- find . -type l | while read -r link; do
- target=$(readlink -f "$link" || true)
- if [ -z "$target" ]; then
- echo "Skipping broken symlink: $link"
- continue
- fi
-
- rm "$link"
- if [ -d "$target" ]; then
- mkdir -p "$link"
- cp -a "$target/." "$link/"
- else
- cp "$target" "$link"
- fi
- done
+ run: bash .github/scripts/resolve_symlinks.sh
- name: Copy templates into addon build context
env:
diff --git a/claude_desktop/CHANGELOG.md b/claude_desktop/CHANGELOG.md
index 8c91b8eb44..c1778d5f7b 100644
--- a/claude_desktop/CHANGELOG.md
+++ b/claude_desktop/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.36.3 (28-07-2026)
+
+- Make the Selkies startup scripts add-on agnostic so `webtop` and `webtop_kde` can share them by symlink instead of carrying their own drifted copies. `20-folders.sh` now derives its default data location from the home directory the Dockerfile baked into the `abc` user (`getent passwd abc`) rather than hardcoding `/data/data`, and the `permission_mode: bypass` root guard is skipped on add-ons that do not declare that option. `80-configuration.sh` falls back to `pip` when the image does not ship `uv`. No behaviour change for Claude Desktop: `getent passwd abc` returns `/data/data`, which is exactly the value that was hardcoded before.
+
## 1.36.2 (28-07-2026)
- Minor bugs fixed
diff --git a/claude_desktop/config.yaml b/claude_desktop/config.yaml
index 43c4a22baa..59e4a0ac0d 100644
--- a/claude_desktop/config.yaml
+++ b/claude_desktop/config.yaml
@@ -122,5 +122,5 @@ slug: claude_desktop
tmpfs: true
udev: true
url: https://github.com/alexbelgium/hassio-addons
-version: "1.36.2"
+version: "1.36.3"
video: true
diff --git a/claude_desktop/rootfs/etc/cont-init.d/20-folders.sh b/claude_desktop/rootfs/etc/cont-init.d/20-folders.sh
index 845c9aa3d9..f2ab418d0a 100755
--- a/claude_desktop/rootfs/etc/cont-init.d/20-folders.sh
+++ b/claude_desktop/rootfs/etc/cont-init.d/20-folders.sh
@@ -3,6 +3,33 @@
# shellcheck disable=SC2046
set -e
+# Shared by every Selkies-based add-on in this repo (claude_desktop, webtop, webtop_kde) via a
+# symlink; keep it add-on agnostic. The only per-add-on input is the home directory baked into
+# the image by the Dockerfile's `usermod --home
abc`, read back below.
+
+# Default data location for this image: whatever the Dockerfile set as abc's home.
+#
+# Cached in a marker file rather than read from /etc/passwd on every boot, because this script
+# rewrites that entry further down to the *selected* location. On a restart that reuses the
+# container's writable layer, re-reading /etc/passwd would hand back the previous selection as
+# the "image default", so clearing data_location would strand the user on their old custom path
+# instead of restoring the built-in one. The marker shares its lifetime with the /etc/passwd
+# edit it compensates for: both live in the writable layer, so a rebuilt or recreated container
+# starts from a pristine /etc/passwd and regenerates the marker correctly.
+#
+# The `|| true` is load-bearing: getent exits 2 when the user does not exist, and under bashio's
+# `set -o pipefail` plus this script's `set -e` that aborts the script at the assignment, before
+# the fallback below can run. Same trap documented in 21-gpu_permissions.sh.
+DEFAULT_LOCATION_MARKER="/etc/.addon_image_home"
+if [ ! -s "$DEFAULT_LOCATION_MARKER" ]; then
+ getent passwd abc 2> /dev/null | cut -d: -f6 > "$DEFAULT_LOCATION_MARKER" || true
+fi
+DEFAULT_LOCATION="$(cat "$DEFAULT_LOCATION_MARKER" 2> /dev/null || true)"
+if [[ -z "$DEFAULT_LOCATION" || "$DEFAULT_LOCATION" == "/" ]]; then
+ DEFAULT_LOCATION="/config/data"
+ bashio::log.warning "Could not read the abc home directory from /etc/passwd; defaulting to $DEFAULT_LOCATION"
+fi
+
# Align the shared desktop user (abc) with the configured PUID/PGID before any storage is
# chowned and before any service or s6-setuidgid call resolves abc. The base image's
# init-adduser applies the same remap, but it runs after cont-init, so doing it here first is
@@ -11,8 +38,8 @@ PUID="$(if bashio::config.has_value 'PUID'; then bashio::config 'PUID'; else ech
PGID="$(if bashio::config.has_value 'PGID'; then bashio::config 'PGID'; else echo '1000'; fi)"
# Claude Code refuses bypass-permissions mode under an effective root UID, so bypass mode
-# always needs a non-root desktop user.
-if [ "$(bashio::config 'permission_mode')" = "bypass" ] && [ "$PUID" -eq 0 ]; then
+# always needs a non-root desktop user. Add-ons without a permission_mode option skip this.
+if bashio::config.has_value 'permission_mode' && [ "$(bashio::config 'permission_mode')" = "bypass" ] && [ "$PUID" -eq 0 ]; then
bashio::log.warning "permission_mode: bypass cannot run Claude Code as root; using UID 1000 instead of the configured PUID 0"
PUID=1000
fi
@@ -37,7 +64,7 @@ fi
LOCATION="$(bashio::config 'data_location')"
if [[ "$LOCATION" = "null" || -z "$LOCATION" ]]; then
- LOCATION="/data/data"
+ LOCATION="$DEFAULT_LOCATION"
else
LOCATIONOK=""
for location in "/share" "/config" "/data" "/mnt"; do
@@ -47,7 +74,7 @@ else
done
if [ -z "$LOCATIONOK" ]; then
- LOCATION="/data/data"
+ LOCATION="$DEFAULT_LOCATION"
bashio::log.fatal "Your data_location value can only be set in /share, /config, /data or /mnt. It will be reset to the default location : $LOCATION"
fi
fi
@@ -73,11 +100,15 @@ for file in /etc/s6-overlay/s6-rc.d/*/run; do
fi
done
-for folders in /defaults /etc/cont-init.d /etc/services.d /etc/s6-overlay/s6-rc.d; do
- if [ -d "$folders" ]; then
- find "$folders" -type f -exec sed -i "s|/data/data|$LOCATION|g" {} + &> /dev/null || true
- fi
-done
+# Rewrite the home path baked into the image to the user-chosen one. No-op when data_location
+# is left at its default.
+if [ "$LOCATION" != "$DEFAULT_LOCATION" ]; then
+ for folders in /defaults /etc/cont-init.d /etc/services.d /etc/s6-overlay/s6-rc.d; do
+ if [ -d "$folders" ]; then
+ find "$folders" -type f -exec sed -i "s|$DEFAULT_LOCATION|$LOCATION|g" {} + &> /dev/null || true
+ fi
+ done
+fi
sed -i "s|^\(abc:[^:]*:[^:]*:[^:]*:[^:]*:\)[^:]*|\1$LOCATION|" /etc/passwd
diff --git a/claude_desktop/rootfs/etc/cont-init.d/80-configuration.sh b/claude_desktop/rootfs/etc/cont-init.d/80-configuration.sh
index fec6070156..ea7c4320e1 100755
--- a/claude_desktop/rootfs/etc/cont-init.d/80-configuration.sh
+++ b/claude_desktop/rootfs/etc/cont-init.d/80-configuration.sh
@@ -2,7 +2,11 @@
# shellcheck shell=bash
set -e
-# The image is Debian-based (apt) and always ships uv, so those are the only installers used.
+# Shared by every Selkies-based add-on in this repo (claude_desktop, webtop, webtop_kde) via a
+# symlink; keep it add-on agnostic. Every option read here is guarded, so an add-on that does
+# not declare a given option simply skips that block.
+#
+# All three images are Debian/Ubuntu-based, so apt is the only system package manager used.
if bashio::config.has_value 'additional_apps'; then
bashio::log.info "Installing additional apps :"
apt-get update -o Acquire::http::Timeout=10 -o Acquire::https::Timeout=10 &> /dev/null || bashio::log.warning "Unable to update apt package lists"
@@ -13,9 +17,14 @@ if bashio::config.has_value 'additional_apps'; then
fi
if bashio::config.has_value 'additional_pip'; then
+ if command -v uv &> /dev/null; then
+ pip_install=(uv pip install --system --break-system-packages)
+ else
+ pip_install=(pip install --break-system-packages)
+ fi
for p in $(bashio::config 'additional_pip' | tr ',' ' '); do
bashio::log.green "... pip: $p"
- uv pip install --system --break-system-packages "$p" || bashio::log.fatal "Error: pip package $p failed"
+ "${pip_install[@]}" "$p" || bashio::log.fatal "Error: pip package $p failed"
done
fi
diff --git a/webtop/CHANGELOG.md b/webtop/CHANGELOG.md
index a2749be943..6c1271393a 100644
--- a/webtop/CHANGELOG.md
+++ b/webtop/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.16-r0-ls95-6 (28-07-2026)
+
+- Share the Selkies startup scripts with the `claude_desktop` add-on by symlink (`20-folders.sh`, `21-gpu_permissions.sh`, `80-configuration.sh`, `90-ingress.sh` and the nginx includes), so the fixes made there now apply here too. This brings in: GPU render-node permissions granted before the graphical services start (fixes `libEGL warning: failed to open /dev/dri/card0: Permission denied` and the resulting "waiting for stream" hang); the s6 envdir and `XDG_RUNTIME_DIR` created up front; the cache redirected to tmpfs; `/tmp/.X11-unix` pre-created so Xorg can bind its socket as a non-root user; the `init-video` and `init-selkies-config` oneshots made non-fatal so a partially permitted device setup no longer crash-loops the add-on; and an ingress config that keeps the correct (non-SSL) nginx server block. The Microsoft Edge install moves to its own webtop-only `81-microsoft_edge.sh`, which also picks up the ownership fixup that previously ran in `20-folders.sh` before Edge was installed and so never matched anything.
+
- Added support for configuring extra environment variables via the `env_vars` add-on option alongside config.yaml. See https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2 for details.
## 4.16-r0-ls95-5 (2026-02-23)
diff --git a/webtop/config.yaml b/webtop/config.yaml
index dfe83b9cac..fc4c23eca7 100644
--- a/webtop/config.yaml
+++ b/webtop/config.yaml
@@ -138,5 +138,5 @@ slug: webtop-kde
tmpfs: true
udev: true
url: https://github.com/alexbelgium/hassio-addons
-version: 4.16-r0-ls95-5
+version: 4.16-r0-ls95-6
video: true
diff --git a/webtop_kde/CHANGELOG.md b/webtop_kde/CHANGELOG.md
index 67c3872032..99cca37427 100644
--- a/webtop_kde/CHANGELOG.md
+++ b/webtop_kde/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.16-r0-ls93.1 (28-07-2026)
+
+- Share the Selkies startup scripts with the `claude_desktop` add-on by symlink (`20-folders.sh`, `21-gpu_permissions.sh`, `80-configuration.sh`, `90-ingress.sh` and the nginx includes), so the fixes made there now apply here too. This brings in: GPU render-node permissions granted before the graphical services start (fixes `libEGL warning: failed to open /dev/dri/card0: Permission denied` and the resulting "waiting for stream" hang); the s6 envdir and `XDG_RUNTIME_DIR` created up front; the cache redirected to tmpfs; `/tmp/.X11-unix` pre-created so Xorg can bind its socket as a non-root user; the `init-video` and `init-selkies-config` oneshots made non-fatal so a partially permitted device setup no longer crash-loops the add-on; and an ingress config that keeps the correct (non-SSL) nginx server block. The Microsoft Edge install moves to its own webtop-only `81-microsoft_edge.sh`, which also picks up the ownership fixup that previously ran in `20-folders.sh` before Edge was installed and so never matched anything.
+
## 4.16-r0-ls93 (2026-07-21)
- Update to latest version from linuxserver/docker-webtop (changelog : https://github.com/linuxserver/docker-webtop/releases)
diff --git a/webtop_kde/config.yaml b/webtop_kde/config.yaml
index b1eda098e4..073e773310 100644
--- a/webtop_kde/config.yaml
+++ b/webtop_kde/config.yaml
@@ -143,5 +143,5 @@ slug: webtop
tmpfs: true
udev: true
url: https://github.com/alexbelgium/hassio-addons
-version: "4.16-r0-ls93"
+version: "4.16-r0-ls93.1"
video: true
diff --git a/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh b/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh
deleted file mode 100755
index a87126ba1c..0000000000
--- a/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# shellcheck shell=bash
-# shellcheck disable=SC2046
-set -e
-
-# Define user
-PUID=$(bashio::config "PUID")
-PGID=$(bashio::config "PGID")
-
-# Set user for microsoft edge if available
-if [ -f /usr/bin/microsoft-edge-real ]; then
- chown "$PUID:$PGID" /usr/bin/microsoft-edge*
- chmod +x /usr/bin/microsoft-edge*
-fi
-
-# Check data location
-LOCATION=$(bashio::config 'data_location')
-
-if [[ "$LOCATION" = "null" || -z "$LOCATION" ]]; then
- # Default location
- LOCATION="/config/data_kde"
-else
- # Check if config is located in an acceptable location
- LOCATIONOK=""
- for location in "/share" "/config" "/data" "/mnt"; do
- if [[ "$LOCATION" == "$location"* ]]; then
- LOCATIONOK=true
- fi
- done
-
- if [ -z "$LOCATIONOK" ]; then
- LOCATION="/config/data_kde"
- bashio::log.fatal "Your data_location value can only be set in /share, /config or /data (internal to addon). It will be reset to the default location : $LOCATION"
- fi
-fi
-
-# Set data location
-bashio::log.info "Setting data location to $LOCATION"
-
-# Correct home locations
-for file in /etc/s6-overlay/s6-rc.d/*/run; do
- if [ "$(sed -n '1{/bash/p};q' "$file")" ]; then
- sed -i "1a export HOME=$LOCATION" "$file"
- sed -i "1a export FM_HOME=$LOCATION" "$file"
- fi
-done
-
-# Correct home location
-for folders in /defaults /etc/cont-init.d /etc/services.d /etc/s6-overlay/s6-rc.d; do
- if [ -d "$folders" ]; then
- sed -i "s|/config/data_kde|$LOCATION|g" $(find "$folders" -type f) &> /dev/null || true
- fi
-done
-
-# Change user home
-sed -i "s|^\(abc:[^:]*:[^:]*:[^:]*:[^:]*:\)[^:]*|\1$LOCATION|" /etc/passwd
-#usermod --home "$LOCATION" abc || true
-
-# Add environment variables
-if [ -d /var/run/s6/container_environment ]; then printf "%s" "$LOCATION" > /var/run/s6/container_environment/HOME; fi
-if [ -d /var/run/s6/container_environment ]; then printf "%s" "$LOCATION" > /var/run/s6/container_environment/FM_HOME; fi
-{
- printf "%s\n" "export HOME=\"$LOCATION\""
- printf "%s\n" "export FM_HOME=\"$LOCATION\""
-} >> ~/.bashrc
-
-# Create folder
-echo "Creating $LOCATION"
-mkdir -p "$LOCATION"
-
-# Create cache
-mkdir -p /.cache
-chmod 755 /.cache
-if [ -d "/config/.cache" ]; then
- cp -rf /config/.cache /.cache
- rm -r /config/.cache
-fi
-ln -sf /config/.cache /.cache
-
-# Set ownership
-bashio::log.info "Setting ownership to $PUID:$PGID"
-chown -R "$PUID":"$PGID" "$LOCATION"
-chmod -R 700 "$LOCATION"
diff --git a/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh b/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh
new file mode 120000
index 0000000000..629ed511b9
--- /dev/null
+++ b/webtop_kde/rootfs/etc/cont-init.d/20-folders.sh
@@ -0,0 +1 @@
+../../../../claude_desktop/rootfs/etc/cont-init.d/20-folders.sh
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/cont-init.d/21-gpu_permissions.sh b/webtop_kde/rootfs/etc/cont-init.d/21-gpu_permissions.sh
new file mode 120000
index 0000000000..55bb6c8b96
--- /dev/null
+++ b/webtop_kde/rootfs/etc/cont-init.d/21-gpu_permissions.sh
@@ -0,0 +1 @@
+../../../../claude_desktop/rootfs/etc/cont-init.d/21-gpu_permissions.sh
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/cont-init.d/80-configuration.sh b/webtop_kde/rootfs/etc/cont-init.d/80-configuration.sh
deleted file mode 100755
index cc347cec90..0000000000
--- a/webtop_kde/rootfs/etc/cont-init.d/80-configuration.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/with-contenv bashio
-# shellcheck shell=bash
-# shellcheck disable=SC2015
-set -e
-
-# Install specific apps
-if bashio::config.has_value 'additional_apps'; then
- bashio::log.info "Installing additional apps :"
- # hadolint ignore=SC2005
- NEWAPPS=$(bashio::config 'additional_apps')
- for packagestoinstall in ${NEWAPPS//,/ }; do
- bashio::log.green "... $packagestoinstall"
- if command -v "apk" &> /dev/null; then
- apk add --no-cache "$packagestoinstall" &> /dev/null || (bashio::log.fatal "Error : $packagestoinstall not found")
- elif command -v "apt" &> /dev/null; then
- apt-get install -yqq --no-install-recommends "$packagestoinstall" &> /dev/null || (bashio::log.fatal "Error : $packagestoinstall not found")
- elif command -v "pacman" &> /dev/null; then
- pacman --noconfirm -S "$packagestoinstall" &> /dev/null || (bashio::log.fatal "Error : $packagestoinstall not found")
- fi
- done
-fi
-
-# Set TZ
-if bashio::config.has_value 'TZ'; then
- TIMEZONE=$(bashio::config 'TZ')
- bashio::log.info "Setting timezone to $TIMEZONE"
- ln -snf /usr/share/zoneinfo/"$TIMEZONE" /etc/localtime
- echo "$TIMEZONE" > /etc/timezone
-fi || (bashio::log.fatal "Error : $TIMEZONE not found. Here is a list of valid timezones : https://manpages.ubuntu.com/manpages/focal/man3/DateTime::TimeZone::Catalog.3pm.html")
-
-# Set keyboard
-if bashio::config.has_value 'KEYBOARD'; then
- KEYBOARD=$(bashio::config 'KEYBOARD')
- bashio::log.info "Setting keyboard to $KEYBOARD"
- if [ -d /var/run/s6/container_environment ]; then printf "%s" "$KEYBOARD" > /var/run/s6/container_environment/KEYBOARD; fi
- printf "%s\n" "KEYBOARD=\"$KEYBOARD\"" >> ~/.bashrc
-fi || true
-
-# Set password
-if bashio::config.has_value 'PASSWORD'; then
- bashio::log.info "Setting password to the value defined in options"
- PASSWORD=$(bashio::config 'PASSWORD')
- passwd -d abc
- echo -e "$PASSWORD\n$PASSWORD" | passwd abc
-elif ! bashio::config.has_value 'PASSWORD' && [[ -n "$(bashio::addon.port "3000")" ]] && [[ -n $(bashio::addon.port "3001") ]]; then
- bashio::log.warning "SEVERE RISK IDENTIFIED"
- bashio::log.warning "You are opening an external port but your password is not defined"
- bashio::log.warning "You risk being hacked ! Please disable the external ports, or use a password"
-fi
-
-# Set password
-if bashio::config.true 'install_ms_edge'; then
- bashio::log.info "Adding microsoft edge"
- # Install edge
- apt-get update
- echo "**** install edge ****"
- apt-get install --no-install-recommends -y ca-certificates
- if [ -z ${EDGE_VERSION+x} ]; then
- EDGE_VERSION=$(curl -sL https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/ \
- | awk -F'( 0' "${NGINX_CONFIG}" > tmpfile
-mv tmpfile "${NGINX_CONFIG}"
-
-# Remove ipv6
-sed -i '/listen \[::\]/d' "${NGINX_CONFIG}"
-# Add ingress parameters
-sed -i "s|3000|$(bashio::addon.ingress_port)|g" "${NGINX_CONFIG}"
-sed -i "s|CWS|8082|g" "${NGINX_CONFIG}"
-sed -i "s|SUBFOLDER|/|g" "${NGINX_CONFIG}"
-sed -i '/proxy_buffering/a proxy_set_header Accept-Encoding "";' "${NGINX_CONFIG}"
-sed -i '/proxy_buffering/a sub_filter_once off;' "${NGINX_CONFIG}"
-sed -i '/proxy_buffering/a sub_filter_types *;' "${NGINX_CONFIG}"
-sed -i '/proxy_buffering/a sub_filter "vnc/index.html?autoconnect" "vnc/index.html?path=%%path%%/websockify?autoconnect";' "${NGINX_CONFIG}"
-sed -i "s|%%path%%|${SUBFOLDER:1}|g" "${NGINX_CONFIG}"
-
-# Enable ingress
-cp "${NGINX_CONFIG}" /etc/nginx/sites-enabled
diff --git a/webtop_kde/rootfs/etc/cont-init.d/90-ingress.sh b/webtop_kde/rootfs/etc/cont-init.d/90-ingress.sh
new file mode 120000
index 0000000000..8808b56360
--- /dev/null
+++ b/webtop_kde/rootfs/etc/cont-init.d/90-ingress.sh
@@ -0,0 +1 @@
+../../../../claude_desktop/rootfs/etc/cont-init.d/90-ingress.sh
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/mime.types b/webtop_kde/rootfs/etc/nginx/includes/mime.types
deleted file mode 100644
index 7c7cdef2d1..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/mime.types
+++ /dev/null
@@ -1,96 +0,0 @@
-types {
- text/html html htm shtml;
- text/css css;
- text/xml xml;
- image/gif gif;
- image/jpeg jpeg jpg;
- application/javascript js;
- application/atom+xml atom;
- application/rss+xml rss;
-
- text/mathml mml;
- text/plain txt;
- text/vnd.sun.j2me.app-descriptor jad;
- text/vnd.wap.wml wml;
- text/x-component htc;
-
- image/png png;
- image/svg+xml svg svgz;
- image/tiff tif tiff;
- image/vnd.wap.wbmp wbmp;
- image/webp webp;
- image/x-icon ico;
- image/x-jng jng;
- image/x-ms-bmp bmp;
-
- font/woff woff;
- font/woff2 woff2;
-
- application/java-archive jar war ear;
- application/json json;
- application/mac-binhex40 hqx;
- application/msword doc;
- application/pdf pdf;
- application/postscript ps eps ai;
- application/rtf rtf;
- application/vnd.apple.mpegurl m3u8;
- application/vnd.google-earth.kml+xml kml;
- application/vnd.google-earth.kmz kmz;
- application/vnd.ms-excel xls;
- application/vnd.ms-fontobject eot;
- application/vnd.ms-powerpoint ppt;
- application/vnd.oasis.opendocument.graphics odg;
- application/vnd.oasis.opendocument.presentation odp;
- application/vnd.oasis.opendocument.spreadsheet ods;
- application/vnd.oasis.opendocument.text odt;
- application/vnd.openxmlformats-officedocument.presentationml.presentation
- pptx;
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
- xlsx;
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
- docx;
- application/vnd.wap.wmlc wmlc;
- application/x-7z-compressed 7z;
- application/x-cocoa cco;
- application/x-java-archive-diff jardiff;
- application/x-java-jnlp-file jnlp;
- application/x-makeself run;
- application/x-perl pl pm;
- application/x-pilot prc pdb;
- application/x-rar-compressed rar;
- application/x-redhat-package-manager rpm;
- application/x-sea sea;
- application/x-shockwave-flash swf;
- application/x-stuffit sit;
- application/x-tcl tcl tk;
- application/x-x509-ca-cert der pem crt;
- application/x-xpinstall xpi;
- application/xhtml+xml xhtml;
- application/xspf+xml xspf;
- application/zip zip;
-
- application/octet-stream bin exe dll;
- application/octet-stream deb;
- application/octet-stream dmg;
- application/octet-stream iso img;
- application/octet-stream msi msp msm;
-
- audio/midi mid midi kar;
- audio/mpeg mp3;
- audio/ogg ogg;
- audio/x-m4a m4a;
- audio/x-realaudio ra;
-
- video/3gpp 3gpp 3gp;
- video/mp2t ts;
- video/mp4 mp4;
- video/mpeg mpeg mpg;
- video/quicktime mov;
- video/webm webm;
- video/x-flv flv;
- video/x-m4v m4v;
- video/x-mng mng;
- video/x-ms-asf asx asf;
- video/x-ms-wmv wmv;
- video/x-msvideo avi;
-}
diff --git a/webtop_kde/rootfs/etc/nginx/includes/mime.types b/webtop_kde/rootfs/etc/nginx/includes/mime.types
new file mode 120000
index 0000000000..bcff4e221b
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/mime.types
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/mime.types
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf b/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf
deleted file mode 100644
index 1990d49596..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-proxy_http_version 1.1;
-proxy_ignore_client_abort off;
-proxy_read_timeout 86400s;
-proxy_redirect off;
-proxy_send_timeout 86400s;
-proxy_max_temp_file_size 0;
-
-proxy_set_header Accept-Encoding "";
-proxy_set_header Connection $connection_upgrade;
-proxy_set_header Host $http_host;
-proxy_set_header Upgrade $http_upgrade;
-proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-proxy_set_header X-Forwarded-Proto $scheme;
-proxy_set_header X-NginX-Proxy true;
-proxy_set_header X-Real-IP $remote_addr;
diff --git a/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf b/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf
new file mode 120000
index 0000000000..f96d9e74d2
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/proxy_params.conf
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/proxy_params.conf
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/resolver.conf b/webtop_kde/rootfs/etc/nginx/includes/resolver.conf
deleted file mode 100644
index 70f4982b9b..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/resolver.conf
+++ /dev/null
@@ -1 +0,0 @@
-resolver 127.0.0.11 ipv6=off;
diff --git a/webtop_kde/rootfs/etc/nginx/includes/resolver.conf b/webtop_kde/rootfs/etc/nginx/includes/resolver.conf
new file mode 120000
index 0000000000..76e3fade4e
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/resolver.conf
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/resolver.conf
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/server_params.conf b/webtop_kde/rootfs/etc/nginx/includes/server_params.conf
deleted file mode 100644
index 09c06543ea..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/server_params.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-root /dev/null;
-server_name $hostname;
-
-add_header X-Content-Type-Options nosniff;
-add_header X-XSS-Protection "1; mode=block";
-add_header X-Robots-Tag none;
diff --git a/webtop_kde/rootfs/etc/nginx/includes/server_params.conf b/webtop_kde/rootfs/etc/nginx/includes/server_params.conf
new file mode 120000
index 0000000000..22db18509c
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/server_params.conf
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/server_params.conf
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf b/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf
deleted file mode 100644
index 6f15005998..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-ssl_protocols TLSv1.2;
-ssl_prefer_server_ciphers on;
-ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
-ssl_ecdh_curve secp384r1;
-ssl_session_timeout 10m;
-ssl_session_cache shared:SSL:10m;
-ssl_session_tickets off;
-ssl_stapling on;
-ssl_stapling_verify on;
diff --git a/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf b/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf
new file mode 120000
index 0000000000..f0235e59e9
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/ssl_params.conf
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/ssl_params.conf
\ No newline at end of file
diff --git a/webtop_kde/rootfs/etc/nginx/includes/upstream.conf b/webtop_kde/rootfs/etc/nginx/includes/upstream.conf
deleted file mode 100644
index b292326bd7..0000000000
--- a/webtop_kde/rootfs/etc/nginx/includes/upstream.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-upstream backend {
- server 127.0.0.1:8080;
-}
diff --git a/webtop_kde/rootfs/etc/nginx/includes/upstream.conf b/webtop_kde/rootfs/etc/nginx/includes/upstream.conf
new file mode 120000
index 0000000000..f64ccbb645
--- /dev/null
+++ b/webtop_kde/rootfs/etc/nginx/includes/upstream.conf
@@ -0,0 +1 @@
+../../../../../claude_desktop/rootfs/etc/nginx/includes/upstream.conf
\ No newline at end of file