fix(server): docker-runtime proxy handler hardcodes resolve_internal=True — server-proxy hangs when lifecycle server runs in a container with bridge sandboxes

Author: zhfktCreated Sep 16, 2026Updated Sep 18, 2026

name: Bug Report about: proxy handler ignores [proxy].resolve_internal and [docker].host_ip — server-proxy data plane hangs in containerized-server + bridge-sandbox topology title: "fix(server): docker-runtime proxy handler hardcodes resolve_internal=True — server-proxy hangs when lifecycle server runs in a container with bridge sandboxes" labels: '' assignees: ''

Why do you need it?

In release server/v0.2.3, the docker-runtime HTTP proxy handler hardcodes resolve_internal=True, so the forwarding target is always resolved to the sandbox's bridge container IP:

python
# server/opensandbox_server/api/proxy.py (v0.2.3)
async def _proxy_http_request(...):
    endpoint = lifecycle.sandbox_service.get_endpoint(sandbox_id, port, resolve_internal=True)

This breaks the exact topology that the repository's own server/docker-compose.example.yaml describes and claims to support:

  • The lifecycle server runs in a container attached to a compose network (e.g. 192.168.48.x)
  • Sandboxes are created through the mounted docker.sock on Docker's default bridge (172.17.0.x)
  • The example config sets [proxy] resolve_internal = false and [docker] host_ip = "host.docker.internal" (with extra_hosts: host-gateway) precisely so the proxy forwards via the host-mapped port instead of the unreachable sandbox IP

With resolve_internal=True hardcoded, the proxy forwards to 172.17.0.x:44772, which is unreachable from the server's compose network. The forwarding request hangs until the client times out. Since the Python SDK's connect() ready-check pings through this exact proxy route, every sandbox creation fails with SandboxReadyTimeoutException: Sandbox health check timed out after 30.0s (1 attempts) — the very first ping consumes the whole window.

Observed in our deployment (recent v0.2.3 image, both server and sandboxes on the same host):

Probe Result
host → sandbox mapped port /ping (host.docker.internal:<mapped> and localhost:<mapped>) 200
server container → host.docker.internal:<mapped> (httpx, same lib as proxy) 200
client → server /v1/sandboxes/{id}/proxy/44772/ping hangs until client timeout

Note that [proxy].resolve_internal = false and [docker].host_ip are already read by docker/networking.py::get_endpoint() when called with use_proxy_host=True — the config keys exist and are documented for this scenario; only the proxy handler never passes them.

How could it be?

Read the config in the proxy handler instead of hardcoding, i.e. what commit 93f7d2bc ("feat(server): make proxy resolve_internal configurable") already does on main:

python
resolve_internal = get_config().proxy.resolve_internal
endpoint = lifecycle.sandbox_service.get_endpoint(
    sandbox_id,
    port,
    resolve_internal=resolve_internal,
    use_proxy_host=not resolve_internal,
)

However, 93f7d2bc has not been included in any release (the latest, server/v0.2.3, was tagged 2026-08-26 and diverged before the fix). Request: cut a patch release containing 93f7d2bc so containerized-server deployments can use the server-proxy data plane again.

Other related information

  • Fix commit on main: 93f7d2bc — verified that it replaces the hardcoded resolve_internal=True with get_config().proxy.resolve_internal (plus use_proxy_host=not resolve_internal)
  • server/docker-compose.example.yaml sets [proxy] resolve_internal = false with the comment "Route through host-published ports instead of unreachable sandbox IPs" — on v0.2.3 this setting has no effect on the forwarding path
  • Docs reference: docs/architecture/single-host-network.md describes the host-mapped routing model that depends on this fix
  • Workaround: run the caller on the same host as the sandboxes and use direct (use_server_proxy=False) + host.docker.internal resolution — works, but loses the single-host port-multiplexing benefit and requires the caller to resolve host_ip

Source: opensandbox-group/OpenSandbox