Skip to content

(uv) extension iframes hardcoded to 127.0.0.1:7769 — breaks all remote/cloud deployments #673

Description

@kusayuzayushko

Summary

(uv) extension iframes are hardcoded to http://127.0.0.1:7769/{package_name}/. This makes them unusable in any deployment where the user's browser isn't running on the same host as the container — i.e. essentially every cloud GPU deployment (RunPod, Vast.ai, Simplepod, etc.). The browser interprets 127.0.0.1 as the user's own machine and either fails ("connection refused") or hits whatever happens to be listening on the user's local 7769.

The same problem applies to GRADIO_TREE_PORT — it's a fixed port number, but cloud platforms typically assign random external ports per launch, so even mapping 7769 externally doesn't reliably give the browser the correct URL.

Reproduction

  1. Run TTS-WebUI on any cloud GPU host with port-mapping (e.g. external port 20005 → container 7770).
  2. Browse to http://<external-host>:20005/.
  3. Install any (uv) extension (e.g. OmniVoice).
  4. Click Start. The iframe attempts to load http://127.0.0.1:7769/tts_webui_extension.omnivoice/.
  5. Browser errors out (refused to connect if nothing is on local 7769).

Root cause

tts_webui/gradio_proxy_tree/main.py:

GRADIO_TREE_PORT = 7769
GRADIO_TREE_HOSTNAME = "127.0.0.1"

tts_webui/extensions_loader/setup_proxy_extension.py:

iframe = f'<iframe src="http://{GRADIO_TREE_HOSTNAME}:{GRADIO_TREE_PORT}/{package_name}/" style="width: 100%; height: 100vh;"></iframe>'

The iframe URL is rendered server-side using container-local values, but the iframe is loaded by the user's browser which has no way to reach 127.0.0.1 of the container.

Suggested fix

Make the iframe URL relative so the browser auto-uses the parent page's host/port:

iframe = f'<iframe src="/{package_name}/" style="width: 100%; height: 100vh;"></iframe>'

For the relative URL to work, the proxy tree and the main Gradio app must share a single port. Two options:

  1. Front Gradio with the proxy tree on the user-facing port. Move main Gradio to an internal-only port (e.g. 7771), bind the proxy tree on the user-facing port (7770), and add a fallback route forwarding unmatched paths to the relocated Gradio:

    GRADIO_TREE_PORT = 7770   # was 7769
    
    def _setup():
        gradio_proxy_tree.add_route("/main-app", 7771)
        gradio_proxy_tree.add_route("", 7771)   # fallback to main Gradio
        gradio_proxy_tree.start_background()

    And update Gradio's default server_port to 7771 in tts_webui/config/load_config.py.

  2. Mount the proxy tree's _RouteDispatcher as ASGI middleware on Gradio's FastAPI app. Cleaner architecturally (single uvicorn, no extra port juggling), but requires hooking into Gradio's launch path.

Either way, the iframe URL becomes relative and the deployment becomes portable.

Workaround (sed-patch in Dockerfile, option 1)

Confirmed working on Simplepod with random external port assignment:

RUN sed -i 's|"server_port": 7770,|"server_port": 7771,|' \
      tts_webui/config/load_config.py && \
    sed -i \
      -e 's|^GRADIO_TREE_PORT = 7769$|GRADIO_TREE_PORT = 7770|' \
      -e 's|gradio_proxy_tree.add_route("/main-app", 7770)|gradio_proxy_tree.add_route("/main-app", 7771)\n    gradio_proxy_tree.add_route("", 7771)|' \
      tts_webui/gradio_proxy_tree/main.py && \
    sed -i 's|http://{GRADIO_TREE_HOSTNAME}:{GRADIO_TREE_PORT}/|/|g' \
      tts_webui/extensions_loader/setup_proxy_extension.py

Environment

  • OS: Ubuntu 22.04 (Docker, nvidia/cuda:12.8.0-devel-ubuntu22.04)
  • Python: 3.10
  • tts-webui: main
  • Cloud platform: Simplepod (random external port mapping per EXPOSEd container port)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions