From b4616e60fd5fe15123e85d1627474eef07781f15 Mon Sep 17 00:00:00 2001 From: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> Date: Fri, 4 Sep 2026 10:53:02 +0800 Subject: [PATCH] fix(skill): derive registry URL for default installs Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> --- .../tests/web-base-path-nginx-smoke-test.sh | 41 ++++++++++++++++++- web/docker-entrypoint.d/30-runtime-config.sh | 8 +++- web/nginx.conf.template | 6 +++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/scripts/tests/web-base-path-nginx-smoke-test.sh b/scripts/tests/web-base-path-nginx-smoke-test.sh index 74793c36..aac6b737 100755 --- a/scripts/tests/web-base-path-nginx-smoke-test.sh +++ b/scripts/tests/web-base-path-nginx-smoke-test.sh @@ -19,7 +19,7 @@ port=18080 tmp=$(mktemp -d) cleanup() { - docker rm -f "$name" "$name-fixed" >/dev/null 2>&1 || true + docker rm -f "$name" "$name-fixed" "$name-default" >/dev/null 2>&1 || true rm -rf "$tmp" } trap cleanup EXIT @@ -126,6 +126,45 @@ fi docker rm -f "$name" >/dev/null 2>&1 || true +# With no explicit public URL, the guide must derive the registry from the +# sanitized request scheme, Host (including port), and deployment base path. +default_html="$tmp/default-html" +mkdir -p "$default_html/assets" "$default_html/install" "$default_html/registry" +printf '%s\n' 'INDEX_HTML_MARKER' >"$default_html/index.html" +cp "$ROOT_DIR/web/src/docs/skill.md.template" "$default_html/registry/skill.md.template" +cp "$ROOT_DIR/web/runtime-config.js.template" "$default_html/runtime-config.js.template" +name_default="$name-default" +port_default=18082 +docker run -d --name "$name_default" \ + -p "$port_default:80" \ + -e SKILLHUB_API_UPSTREAM=http://127.0.0.1:9 \ + -e SKILLHUB_TRUST_FORWARDED_PROTO=false \ + -e SKILLHUB_WEB_BASE_PATH=/ \ + -v "$default_html:/usr/share/nginx/html" \ + -v "$ROOT_DIR/web/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro" \ + -v "$entrypoint_d/20-base-path.sh:/docker-entrypoint.d/20-base-path.sh:ro" \ + -v "$entrypoint_d/30-runtime-config.sh:/docker-entrypoint.d/30-runtime-config.sh:ro" \ + "$NGINX_IMAGE" >/dev/null + +default_base="http://127.0.0.1:$port_default" +i=0 +until curl -fsS -o /dev/null "$default_base/nginx-health" 2>/dev/null; do + i=$((i + 1)) + if [ "$i" -ge 30 ]; then + echo 'nginx (default public URL) did not become ready' >&2 + docker logs "$name_default" >&2 || true + exit 1 + fi + sleep 1 +done +default_guide=$(curl -fsS "$default_base/install/skillhub.md") +printf '%s' "$default_guide" | grep -F "The primary registry for this guide is \`$default_base\`." >/dev/null +if printf '%s' "$default_guide" | grep -F '__SKILLHUB_PUBLIC_BASE_URL__' >/dev/null; then + echo 'default Agent guide must not expose the runtime URL marker' >&2 + exit 1 +fi +docker rm -f "$name_default" >/dev/null 2>&1 || true + # Fixed-base image served via the bundled deploy configs: assets are baked under # /fixed/, a baked-base marker is present, and SKILLHUB_WEB_BASE_PATH is passed as # an empty string (as compose.release.yml / k8s do). Routing must follow the baked diff --git a/web/docker-entrypoint.d/30-runtime-config.sh b/web/docker-entrypoint.d/30-runtime-config.sh index 0de561dc..952b286d 100644 --- a/web/docker-entrypoint.d/30-runtime-config.sh +++ b/web/docker-entrypoint.d/30-runtime-config.sh @@ -24,7 +24,13 @@ envsubst '${SKILLHUB_WEB_API_BASE_URL} ${SKILLHUB_PUBLIC_BASE_URL} ${SKILLHUB_WE # Generate both the preferred install guide and the compatibility route from # one template so self-hosted deployments keep their own registry URL. mkdir -p /usr/share/nginx/html/install -envsubst '${SKILLHUB_PUBLIC_BASE_URL}' \ +guide_public_base_url="$SKILLHUB_PUBLIC_BASE_URL" +if [ -z "$guide_public_base_url" ]; then + # Nginx replaces this marker from the sanitized request scheme, Host, and + # configured base path. This keeps zero-config self-hosted installs usable. + guide_public_base_url='__SKILLHUB_PUBLIC_BASE_URL__' +fi +SKILLHUB_PUBLIC_BASE_URL="$guide_public_base_url" envsubst '${SKILLHUB_PUBLIC_BASE_URL}' \ < /usr/share/nginx/html/registry/skill.md.template \ > /usr/share/nginx/html/registry/skill.md cp /usr/share/nginx/html/registry/skill.md /usr/share/nginx/html/install/skillhub.md diff --git a/web/nginx.conf.template b/web/nginx.conf.template index 0bddd9a4..acc55bc4 100644 --- a/web/nginx.conf.template +++ b/web/nginx.conf.template @@ -75,6 +75,9 @@ server { location = /registry/skill.md { default_type text/plain; + sub_filter_types text/plain; + sub_filter_once off; + sub_filter '__SKILLHUB_PUBLIC_BASE_URL__' '$proxy_x_forwarded_proto://$http_host$skillhub_forwarded_prefix'; add_header Cache-Control "no-cache"; add_header Content-Disposition "inline"; add_header X-Content-Type-Options "nosniff"; @@ -83,6 +86,9 @@ server { location = /install/skillhub.md { default_type text/plain; + sub_filter_types text/plain; + sub_filter_once off; + sub_filter '__SKILLHUB_PUBLIC_BASE_URL__' '$proxy_x_forwarded_proto://$http_host$skillhub_forwarded_prefix'; add_header Cache-Control "no-cache"; add_header Content-Disposition "inline"; add_header X-Content-Type-Options "nosniff";