feat(#758): Remote GPU Node — Standalone Compose + Ansible + nginx Proxy
Summary
Remote GPU node architecture for GENIE.AI (#758 (closed)). Deploys AI model services (vLLM, TEI, docling-serve) on a dedicated GPU node behind nginx with TLS termination, API key authentication, and path-based routing on port 443.
Changes
GPU Node (deploy-gpu.yml)
-
Path-based routing on port 443:
/llm/,/translation/,/embed/,/rerank/,/docling/ -
nginx proxy with TLS termination, API key authentication (
X-API-Keyheader) - Self-signed cert generation (configurable, disabled with Let's Encrypt)
- Smoke tests validate all 5 endpoints post-deploy
-
Graceful config reload (
nginx -s reloadon config changes)
App Node (docker-compose.yaml)
-
Dual profiles:
profiles: [opea](orchestrators) vsprofiles: [gpu-models](GPU-heavy) -
GPU_MODEL_REPLICAS: set to 0 in Swarm to skip GPU containers on app node -
Endpoint overrides:
${VAR:-default}pattern for 7 orchestrator services -
Removed
depends_onGPU service refs from 5 orchestrators (Compose-mode compat) -
ChatQnA:
VLLM_LLM_ENDPOINTsupport for remote GPU with HTTPS/protocol/path-prefix -
API key propagation:
OPENAI_API_KEYfromVLLM_API_KEYfor chatqna
Ansible (env.j2, all.yml)
-
Section 18: auto-generates GPU endpoint URLs +
GPU_MODEL_REPLICAS=0whengpu_node_hostset -
New vars:
gpu_node_host,vllm_api_keyingroup_vars/all.yml
Python (genieai_chatqna.py)
-
VLLM_LLM_ENDPOINTenv var support (mirrors existingVLLM_TRANSLATION_ENDPOINT) - URL parsing for host/port/protocol/endpoint prefix
-
protocol=httpspassed to OPEA MicroService for remote endpoints
Tests
- Config validator updated: all ports → 443, legacy port detection, docling image fix
- 24/24 tests passing
Documentation
- CLAUDE.md, ansible README, docker-compose-setup.md, docker-swarm-setup.md, env template
- All
--profilecommands updated for dual-profile architecture - Clear warnings:
DEPLOY_OPEA=0must NOT be used to skip GPU services
Architecture
App node (--profile opea) GPU node (standalone)
┌─────────────────────────┐ ┌─────────────────────────────┐
│ Frontend, Backend, │ │ nginx (port 443, TLS) │
│ ArangoDB, Redis, ... │ HTTPS 443 │ /llm/ → vLLM │
│ │ ──────────── │ /translation/ → vLLM T │
│ ChatQnA ────────────────────────────→ │ /embed/ → TEI Emb │
│ Retriever ──────────────────────────→ │ /rerank/ → TEI Rer │
│ Dataprep ──────────────────────────→ │ /docling/ → docling │
└─────────────────────────┘ └─────────────────────────────┘
Usage
Compose (remote GPU)
GPU_NODE_HOST=<gpu-node-host>
VLLM_API_KEY=<api-key>
docker compose --profile opea up -d
Compose (local GPU)
docker compose --profile opea --profile gpu-models up -d
Swarm (remote GPU)
# In group_vars/<env>/vars.yml:
gpu_node_host: "<gpu-node-host>"
# Ansible auto-sets GPU_MODEL_REPLICAS=0 and endpoint URLs
Default Behavior
Zero impact when GPU_NODE_HOST is not set — all defaults unchanged.
Closes #758 (closed)
Edited by Jérôme Revillard