/explorer-remote-proxy — local Explorer, remote backend
Stand up ONLY the redesigned Explorer + gateway locally and proxy the
entire API surface (/search*, /images, /llm_parse, /vlm_validate,
/asset_graph, /dependency_graph, /download, /info, /process) to a
hosted USD Search instance. The hosted instance already has a populated
index, a populated Asset Graph Service, and storage access, so the
features that need a backend — dependency graphs and downloads — work
with zero local infra.
Why this exists. A local remote-index (BYO-OpenSearch) stack only
borrows the search index; its local AGS is empty, so dependency graphs and
multi-file download bundles come back empty. Proxying straight to a fully
hosted instance sidesteps that — and avoids the https://…s3….amazonaws.com
(index) vs s3://… (AGS) base-key scheme mismatch, because the hosted
instance is internally consistent.
Be terse. No preamble, no per-step narration. Never accept a pasted
secret — for an authenticated target, accept only the NAME of an env var
that already holds the credential (grep ~/.zshrc ~/.zshenv ~/.zprofile ~/.profile ~/.bashrc for export <NAME>=; if absent, ask the user to
export it themselves).
Files (committed, reusable)
docker-compose.staging-hybrid.yml— overlay: swaps the gateway conf and trimsgateway.depends_ontoexploreronly (no local API).infra/quickstart/gateway.staging-hybrid.conf— nginx: every APIlocation→http://api.staging.deepsearch-horde.nvidia.com;/ui,/static,/→ localexplorer.
To target a DIFFERENT hosted instance, copy those two files and change one
line in the conf: set $remote <scheme>://<host>; (and $remote_host).
For HTTPS targets add proxy_ssl_server_name on; per location. For an
AUTHENTICATED target, inject the header per location
(proxy_set_header Authorization "Basic ${AUTH_B64}";) and render the conf
from a .template via the nginx image's envsubst entrypoint — see the
gitignored gateway.isaac-dev-hybrid.conf.template for the pattern.
Steps
1 — Pre-flight
cd <repo root>
docker compose version >/dev/null 2>&1 && echo COMPOSE=ok || echo COMPOSE=missing
docker image inspect usdsearch-explorer:latest >/dev/null 2>&1 && echo EXPLORER_IMG=ok || echo EXPLORER_IMG=missing
curl -s -o /dev/null -w "remote /search_hybrid: %{http_code}\n" --max-time 12 \
-X POST http://api.staging.deepsearch-horde.nvidia.com/search_hybrid \
-H 'Content-Type: application/json' -d '{"query":"box","limit":1}'
COMPOSE=missing→ stop, tell the user to install Docker Compose v2.EXPLORER_IMG=missing→ build it first (it carries the redesigned UI):docker compose -f docker-compose.yml -f docker-compose.web-ui.yml -f docker-compose.staging-hybrid.yml build explorer(run in background; large CRA build).- remote
/search_hybridnot200→ the hosted instance is unreachable (VPN? wrong host?); fix before continuing.
2 — Bring up (only explorer + gateway)
docker compose \
-f docker-compose.yml \
-f docker-compose.web-ui.yml \
-f docker-compose.staging-hybrid.yml \
up -d --wait --no-build explorer gateway
Reuse the exact same -f chain for every later compose command
(down, logs, restart).
3 — Verify end-to-end through the LOCAL gateway
KEY=$(curl -s -X POST http://localhost:8080/search_hybrid -H 'Content-Type: application/json' \
-d '{"query":"pallet","limit":10}' | python3 -c 'import sys,json
for h in json.load(sys.stdin).get("hits",[]):
k=h["source"].get("base_key","")
if k.lower().endswith(".usd"): print(k); break')
ENC=$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))" "$KEY")
curl -s "http://localhost:8080/dependency_graph/graph?root_node_url=$ENC&limit=200" \
| python3 -c 'import sys,json;d=json.load(sys.stdin);print("nodes",len(d.get("nodes",[])),"edges",len(d.get("edges",[])))'
Expect nodes ≥ 2 for a graphed asset. The UI is at
http://localhost:8080/ui/ — hard-refresh, search, open an asset, expand
Dependencies.
Gotchas (seen in practice)
- Empty results grid. The UI defaults to "show only with previews"
(
showOnlyWithPreviews=true, filtersthumbnail_exists === true). If the hosted search omits/false-flagsthumbnail_exists, the grid looks empty even though/imagesworks. Open with?with_previews=false(http://localhost:8080/ui/?with_previews=false) or toggle it off in Display Options. - A query returns nothing. The search box runs through
/llm_parse, which may emit a HARD filter (e.g.category eq traffic_light→filter_by_properties=simready_metadata_type=traffic_light) that excludes every asset lacking that property. Try a plainer term, or open Filters and clear the interpreted-query chip. thumbnail_existsis null in raw curl — it's only set when the request includesreturn_images: true(the UI sends it; ad-hoc curls usually don't). Not a bug.- Dependency graph empty for an asset. That specific asset isn't graphed
on the hosted instance (intermediate
_inst/_baselayers often are); pick the top-level*.usd. - Don't
--buildsiglip2-triton here. This stack never runs it; naming it in anup --buildtriggers an unrelated build failure. Only ever build/upexplorer(+gateway).
Teardown
docker compose -f docker-compose.yml -f docker-compose.web-ui.yml \
-f docker-compose.staging-hybrid.yml down