Reverse Proxy Sub-Path Deployment#
Phoenix supports deployment behind a reverse proxy at a URL sub-path (e.g., https://example.com/phoenix). This requires coordinating three subsystems:
- Uvicorn server — must be told the ASGI
root_pathso it strips the prefix from incoming requests. - Phoenix client (
phoenix-client) — must append the sub-path to every derived API base URL. - Agent-generated links — must use root-relative redirect URLs so they work regardless of the proxy prefix.
The central environment variable is PHOENIX_HOST_ROOT_PATH. It must start with / and must not end with / (e.g., /phoenix is valid; phoenix, /phoenix/ are both invalid) .
Note: Setting only
PHOENIX_HOST_ROOT_PATHis not enough for a complete deployment.PHOENIX_ROOT_URLmust also be set to the full public URL (e.g.,https://example.com/phoenix) so Phoenix can generate correct external links .
Environment Variables#
| Variable | Purpose | Example |
|---|---|---|
PHOENIX_HOST_ROOT_PATH | ASGI root path prefix; passed directly to Uvicorn | /phoenix |
PHOENIX_ROOT_URL | Full public URL for browser access and external link generation | https://example.com/phoenix |
Both variables are defined in src/phoenix/config.py. The default for PHOENIX_HOST_ROOT_PATH is an empty string (no sub-path) .
get_env_host_root_path() validates the value and is shared between the server and client packages .
get_env_root_url() on the server side first checks for an explicit PHOENIX_ROOT_URL; if absent, it constructs the URL from PHOENIX_HOST, PHOENIX_PORT, and PHOENIX_HOST_ROOT_PATH using urljoin .
Server: Uvicorn Configuration#
src/phoenix/server/main.py reads get_env_host_root_path() at startup and passes it directly to Uvicorn's Config object :
host_root_path = get_env_host_root_path()
# ...
server_config = Config(app=app, host=host, port=port, root_path=host_root_path, ...)
This is the standard ASGI root_path mechanism — Starlette/Uvicorn uses it to strip the prefix from incoming request paths before routing them through the application.
The startup banner URL is also constructed with urljoin to include the root path :
display_root_path = urljoin(f"{http_scheme}://{display_host}:{port}", host_root_path)
Client: Base URL Construction#
The phoenix-client package builds a base URL in get_base_url(). Previously, this function omitted PHOENIX_HOST_ROOT_PATH, causing all client API calls to hit the origin root (e.g., /v1/traces) instead of the sub-path (e.g., /phoenix/v1/traces) when deployed behind a reverse proxy.
Two PRs address this:
- PR #13984 (fix(client): include PHOENIX_HOST_ROOT_PATH in default get_base_url()) — appends
get_env_host_root_path()to the fallbackhost:portderived URL. - PR #14054 (fix(client): include PHOENIX_HOST_ROOT_PATH in derived base_url) — extends the fix to also cover collector-endpoint derived URLs (using
rstrip("/")to handle trailing-slash edge cases before joining).
Both fixes are backward-compatible: get_env_host_root_path() returns "" when PHOENIX_HOST_ROOT_PATH is unset . The client-side validation applies the same constraints as the server: value must start with /, must not end with / .
Agent-Generated Trace and Span Links#
The Phoenix debug-trace agent produces markdown links pointing at specific traces and spans. These links must work correctly regardless of the sub-path prefix.
Standardized format : the agent uses root-relative redirect URLs:
- Span link:
/redirects/spans/<spanId> - Trace link:
/redirects/traces/<traceId>
Rules standardized in PR #13498 (fix(agent): guide debug-trace span/trace link formatting):
- Prefer span links over trace links when the issue is localized to a single span.
- Use OTel hex IDs from the
spanIdandtraceIdGraphQL fields — not the Relayidfield.
These root-relative paths navigate through React Router for client-side routing. PR #13345 (fix(app): route PXI markdown links through router) fixed markdown link routing to go through the React Router rather than the browser, and was explicitly tested under PHOENIX_HOST_ROOT_PATH=/phoenix — ensuring sub-path deployments resolve links correctly.
Key Files and Entry Points#
| Component | File | Key Symbols |
|---|---|---|
| Server config | src/phoenix/config.py | get_env_host_root_path(), get_env_root_url(), ENV_PHOENIX_HOST_ROOT_PATH, ENV_PHOENIX_ROOT_URL |
| Server startup | src/phoenix/server/main.py | uvicorn.Config(root_path=host_root_path) |
| Client config | packages/phoenix-client/src/phoenix/client/utils/config.py | get_base_url(), get_env_host_root_path() |
| Agent skill | src/phoenix/server/agents/prompts/skills/debug-trace/SKILL.md | "Linking to Findings" section |
Recent fixes (newest first):
- PR #14054 — client
get_base_url()with collector endpoint derivation - PR #13984 — client
get_base_url()with host+port derivation - PR #13498 — agent span/trace link format standardization
- PR #13345 — PXI markdown link routing through React Router