feat: add reverse proxy support with X-Forwarded-Host header handling for agent installer URL generation
CI / backend (push) Failing after 3s
CI / frontend (push) Failing after 27s

Add external_base_url helper to detect base URL from X-Forwarded-Host and X-Forwarded-Proto headers with fallback to request.base_url, replace hardcoded request.base_url usage in node_agent_install, node_agent_install_info, and public_node_agent_install endpoints to support reverse proxy deployments, update nginx config to pass X-Forwarded-Host header and use $http_host instead of $host for proper hostname forw
This commit is contained in:
2026-07-09 14:21:11 +02:00
parent e67174a4ae
commit ffc69011c4
2 changed files with 14 additions and 6 deletions
+11 -3
View File
@@ -658,6 +658,14 @@ def node_agent_payload(node: Node, agent: NodeAgent | None) -> dict:
}
def external_base_url(request: Request) -> str:
forwarded_host = request.headers.get("x-forwarded-host") or request.headers.get("host")
forwarded_proto = request.headers.get("x-forwarded-proto") or request.url.scheme
if forwarded_host:
return f"{forwarded_proto}://{forwarded_host}".rstrip("/")
return str(request.base_url).rstrip("/")
@api_router.get("/nodes/agents", response_model=list[NodeWithAgentRead])
def nodes_with_agents(_: CurrentUser, db: Session = Depends(get_db)) -> list[dict]:
agents = {agent.node_id: agent for agent in db.scalars(select(NodeAgent)).all()}
@@ -742,7 +750,7 @@ def node_agent_install(node_id: str, request: Request, user: CurrentUser, db: Se
agent.install_count = (agent.install_count or 0) + 1
token = create_token(node.id, "agent", timedelta(days=365), {"node_name": node.name})
write_audit(db, action="agent.install.generated", object_type="node", object_id=node.id, user_id=user.id)
base_url = str(request.base_url).rstrip("/")
base_url = external_base_url(request)
return agent_install_script(base_url, token, node)
@@ -758,7 +766,7 @@ def node_agent_install_info(node_id: str, request: Request, user: CurrentUser, d
agent.install_count = (agent.install_count or 0) + 1
install_token = create_token(node.id, "agent-install", timedelta(days=7), {"node_name": node.name})
write_audit(db, action="agent.install.generated", object_type="node", object_id=node.id, user_id=user.id)
base_url = str(request.base_url).rstrip("/")
base_url = external_base_url(request)
install_url = f"{base_url}/api/v1/agents/install/{node.id}?token={install_token}"
return {
"node_id": node.id,
@@ -779,7 +787,7 @@ def public_node_agent_install(node_id: str, token: str, request: Request, db: Se
if not node:
raise HTTPException(status_code=404, detail="Node not found")
agent_token = create_token(node.id, "agent", timedelta(days=365), {"node_name": node.name})
base_url = str(request.base_url).rstrip("/")
base_url = external_base_url(request)
return agent_install_script(base_url, agent_token, node)