Skip to content

fix: server.eip not used in proxy URL construction when use_server_proxy=True #727

@moxue361

Description

@moxue361

Bug Description

When a client outside the Kubernetes cluster calls
GET /v1/sandboxes/{id}/endpoints/{port}?use_server_proxy=true,
the server returns a proxy URL based on request.base_url — which is
always the internal ClusterIP (e.g. 10.97.x.x) — instead of an
externally reachable address.

This causes all health checks and execd calls to fail with
SandboxReadyTimeoutException for clients outside the cluster.

Root Cause

server/opensandbox_server/api/lifecycle.py constructs the proxy URL like this:

if use_server_proxy:
    base_url = str(request.base_url).rstrip("/")
    base_url = base_url.replace("https://", "").replace("http://", "")
    endpoint.endpoint = f"{base_url}/sandboxes/{sandbox_id}/proxy/{port}"

request.base_url reflects the address the server itself sees after
passing through nginx/ingress, not the original external domain the
client used.

ServerConfig already defines an eip field for exactly this purpose:

# server/opensandbox_server/config.py
eip: Optional[str] = Field(
    default=None,
    description="Bound public IP. When set, used as the host part "
                "when returning sandbox endpoints.",
)

However, eip is never read in lifecycle.py, so setting it in
config.toml has no effect.

Proposed Fix

if use_server_proxy:
    if app_config.server.eip:
        base_url = app_config.server.eip.rstrip("/")
    else:
        base_url = str(request.base_url).rstrip("/")
        base_url = base_url.replace("https://", "").replace("http://", "")
    endpoint.endpoint = f"{base_url}/sandboxes/{sandbox_id}/proxy/{port}"

Operators set in config.toml:

[server]
eip = "sandbox.example.com/opensandbox"

The returned endpoint becomes
sandbox.example.com/opensandbox/sandboxes/{id}/proxy/{port},
reachable by external clients.

Impact

- SandboxReadyTimeoutException on every sandbox creation for external clients
- All sandbox.commands.run() calls fail with connection error
- skip_health_check=True does not helpthe same broken endpoint is
used for all subsequent execd operations

Backwards Compatibility

When eip is not set, behavior is identical to current. Fully backwards
compatible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions