LoxiLB UI¶
A React web dashboard for supported LoxiLB and Inference Gateway management surfaces. Capability depends on the selected UI, OAM, and Gateway releases; verify each required workflow before production use.
Audience
Operators who want a graphical control surface instead of (or alongside) loxicmd and raw REST.
Repository: loxilb-io/loxilb-ui · License: MIT · Stack: React 18 + TypeScript + Material-UI, served as a static SPA by nginx.
What you can do from the UI¶
| Area | Capabilities |
|---|---|
| AI Gateway | Model-based routing, weighted CHWBL, KV-cache-aware routing, prefill/decode disaggregation, SSE streaming services, MCP session routing, API-key and per-tenant rate-limit management |
| Load balancing | L4/L7 rules across all modes (dnat, onearm, fullnat, dsr, fullproxy), all selection algorithms (rr, hash, priority, persist, lc, chwbl), health probes, TLS termination, mTLS |
| Networking | BGP, BFD, VLAN/VXLAN, routes, FDB, ports, neighbors |
| Security & traffic | Firewall rules, IP filters, rate limits, conntrack view, traffic mirrors, QoS, SNI certificates |
| Operations | IPsec VPN, HA cluster state, instance configuration snapshots (backup/restore wizard), real-time Prometheus-backed charts |
| Access control | JWT login with server-side session revocation; admin / operator / viewer roles with route guards; English, Korean, and Japanese localization |
The UI is a pure frontend: it talks to the OAM management API
(default port 8080, base path /oam). OAM authenticates the UI request and
applies OAM RBAC before proxying. Gateway management authentication remains a
separate boundary; OAM does not automatically translate its JWT into a Gateway
credential. A reachable, correctly integrated OAM deployment is a prerequisite
for every install mode below.
Deployment options¶
Evaluate with the management-plane bundle
The management-plane bundle is the shortest setup path: UI + OAM + PostgreSQL behind one TLS edge. Production promotion requires pinned releases, backup recovery, and verified OAM-to-Gateway credentials.
Official container image
Tagged releases publish ghcr.io/loxilb-io/loxilb-ui. Select a release
approved for your environment and replace <UI_RELEASE_TAG> below; do not
copy a mutable tag into production. Verify pullability with
docker manifest inspect ghcr.io/loxilb-io/loxilb-ui:<UI_RELEASE_TAG>.
If the registry denies the pull, build from reviewed source instead.
Option A — Docker Compose (standalone)¶
Pick one of the three SSL modes:
Point the container at your OAM backend by overriding the environment in the compose file (or a docker-compose.override.yml):
| Variable | Default | Purpose |
|---|---|---|
BACKEND_URL |
Unset; operator supplied | OAM backend that nginx proxies /api/oam/* to (<BACKEND_URL>/oam/) |
BACKEND_HOST |
Unset; derived from BACKEND_URL |
Optional override for the Host header sent to the backend |
FRONTEND_URL |
http://localhost:3000 |
Origin/Referer the proxy presents |
PUBLIC_PATH |
/netlox |
URL prefix the SPA is served under |
SSL_MODE |
varies by compose file | enabled (self-signed HTTPS), disabled (HTTP), commercial (your certs) |
A helper script wraps the three modes: ./deploy.sh [http|https|commercial] [up|down|restart|logs|status].
The standalone container templates do not provide a usable OAM destination by
default. Set BACKEND_URL for the deployed OAM endpoint; override
BACKEND_HOST only when the derived host is unsuitable. Verify the rendered
nginx configuration before exposing the UI.
Port 3000 collides with Grafana
The gateway's reference monitoring stack runs Grafana on host port 3000. If both run on the same host, remap the UI's published port in the compose file.
Option B — Kubernetes (Kustomize)¶
Plain manifests with Kustomize support ship in k8s/ — namespace loxilb-system, a 3-replica nginx Deployment with rolling updates, /health liveness/readiness probes, a non-root security context, a PodDisruptionBudget, a ClusterIP Service on 80/443, and an nginx-class Ingress with TLS.
# 1. Pin the released image (k8s/kustomization.yaml already targets
# ghcr.io/loxilb-io/loxilb-ui — set newTag to <UI_RELEASE_TAG>).
# Alternatively build and push to your own registry and reference that
# image instead.
# 2. Create the TLS secret and deploy
./k8s/generate-tls-secret.sh # self-signed loxilb-ui-tls secret
kubectl apply -k k8s/
# 3. Watch the rollout
kubectl -n loxilb-system rollout status deploy/loxilb-ui
The shipped Ingress uses host loxilb-ui.example.com and routes /netlox to the UI and /api to an OAM backend Service — adjust the host, TLS secret, and backend Service name to your environment. k8s/deploy.sh scripts the same flow with IMAGE_TAG, DOMAIN, and SKIP_INGRESS knobs.
No Helm chart
The project ships Kustomize/plain manifests only. There is no Helm chart today.
Option C — Development server¶
Set REACT_APP_API_URL in .env.development to your OAM endpoint (e.g. http://oam.example.com:8080/oam). See the repository's README for the full development, testing (Vitest + Playwright E2E), and API-codegen workflow.
Configuration reference¶
Two layers — don't confuse them:
Build-time (React, baked into the static bundle):
| Variable | Production value | Purpose |
|---|---|---|
REACT_APP_API_URL |
/api/oam |
OAM API base. In production it is a same-origin path that nginx (or Caddy) proxies to the backend; only dev builds point at an absolute URL |
REACT_APP_PUBLIC_URL |
/netlox |
Path prefix the app is served under |
REACT_APP_ENV |
production |
Build profile |
REACT_APP_REPATCH_INTERVAL |
e.g. 5000 |
Data-refresh polling interval (ms) |
Runtime (nginx container, substituted at startup): the BACKEND_URL / BACKEND_HOST / FRONTEND_URL / PUBLIC_PATH / SSL_MODE table above. Because the API base is a same-origin path, switching OAM backends requires only a container restart with new runtime env — no rebuild.
Authentication is a JWT bearer token obtained from OAM's /oam/login, stored client-side and attached to every request; OAM revokes sessions server-side on logout.
Verify¶
# -k skips CA verification for the default self-signed cert; verify the CA in production
# nginx serving and healthy
curl -sk https://<host>:3443/health
# SPA delivered under the /netlox prefix
curl -sk https://<host>:3443/netlox/ | head -5
Then log in with an OAM account. A viewer sees dashboards read-only; operator and admin can change configuration.
Troubleshooting¶
| Symptom | Likely cause | What to check |
|---|---|---|
Blank page at / |
SPA served under /netlox |
Browse to https://<host>:3443/netlox/ |
| Login page loads but login fails / network errors | UI cannot reach OAM through the proxy | BACKEND_URL/BACKEND_HOST point at a reachable OAM; curl -sk https://<host>:3443/api/oam/health |
| CORS errors in the browser console | OAM's allowlist doesn't include the UI origin | Add the exact origin to OAM_ALLOWED_ORIGINS on the OAM side |
| Browser warns about the certificate | Self-signed SSL_MODE=enabled |
Expected for the default mode; use commercial mode or the management-plane bundle's edge TLS for trusted certs |
| Immediate logout / 401 loops | JWT expired or revoked, or OAM restarted with a new OAM_JWT_SECRET |
Log in again; keep OAM_JWT_SECRET stable across OAM restarts |
K8s pods ImagePullBackOff |
Image tag not pullable from the cluster | Verify docker manifest inspect ghcr.io/loxilb-io/loxilb-ui:<tag> succeeds; otherwise build and push your own image and reference it in k8s/kustomization.yaml |
See also¶
- Deploy the Management Plane — UI + OAM + PostgreSQL in one bundle (recommended).
- LoxiLB OAM API — the backend the UI requires.
- Management API Authentication — the independent Gateway-side auth boundary.