A modern React-based web dashboard for efficiently managing LoxiLB load balancers and network services with comprehensive SSL/HTTPS support and multiple deployment options.
Live monitoring on the public demo instance β dashboard health cards, real-time traffic/packet rate charts, streaming gateway logs, load-balancer rules, and endpoint health probes.
LoxiLB UI is a front-end for the loxilb-oam management API β it holds no data and performs no logic itself. Every screen (login, dashboards, all CRUD) is served by talking to a running loxilb-oam backend, which in turn drives the LoxiLB core. Deploying only this container gets you a login page that cannot authenticate anyone β there is nothing behind it.
Before you deploy, make sure you have a reachable OAM backend and point the UI at it (
BACKEND_URL, see Environment Configuration).The recommended way to run the whole management plane (this UI + OAM + its database behind one TLS edge, wired together for you) is the single-node Compose bundle in the OAM repo β start there, not here: loxilb-oam β deploy/compose (operator guide). Run this repo's container standalone only when you already operate an OAM backend elsewhere (see Standalone container).
- Features
- Architecture
- Quick Start
- Docker Deployment
- Kubernetes Deployment
- SSL/HTTPS Configuration
- Development Setup
- Environment Configuration
- API Integration
- Build & Scripts
- Troubleshooting
- Contributing
- Load Balancer Management: L4/L7 rules across every mode (dnat, onearm, fullnat, dsr, fullproxy) with selects (rr, hash, priority, persist, lc, chwbl), health probes, TLS termination (https / e2ehttps), and frontend mTLS
- AI Gateway: model-based routing, weighted CHWBL, KV-cache-aware routing, prefill/decode (P/D) disaggregation, SSE streaming tuning, MCP session routing, plus API-key and per-tenant rate-limit management
- Networking: BGP (neighbors, global, policy, defined-sets, apply), BFD, VLAN/VXLAN, routes, FDB, ports, neighbors
- Security & Traffic: firewall rules, IP filters, SYN-flood protection, security rate limits, conntrack, mirrors, QoS, SNI certificates, endpoints
- IPsec VPN: tunnel and certificate management
- High Availability: cluster instance state (cistate) management
- Instance Snapshots: back up and restore an instance's configuration via a guided wizard
- Real-time Monitoring: live device/service status, Prometheus-backed dashboards and rate cards (MUI X Charts)
- Multi-language Support: Korean, English, and Japanese localization
- Responsive Design: mobile-first Material-UI layout
- Role-Based Access Control: three roles (admin / operator / viewer) with route guards and capability-gated menus and actions
- Authentication: JWT-based login with server-side session revocation on logout; unauthorized/expired sessions redirect to login
- SSL/HTTPS Support: self-signed and commercial certificates
- Docker Ready: multiple compose configurations for different scenarios
- Kubernetes Native: production-ready manifests with security contexts
- Security Headers: HSTS, CSP, and other security best practices
- TypeScript: full type safety; API types generated from the vendored gateway/OAM swagger specs, with a connectorβspec mapping guard in CI
- State Management: Recoil for global state, TanStack React Query for server state
- Hot Reload: fast development with React Scripts (Create React App)
- Testing: Vitest unit + backend-contract tests, and a Playwright end-to-end browser suite (see
docs/E2E_RUNNING.md)
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
β Frontend (React) ββββββ LoxiLB API (OAM) ββββββ LoxiLB Core β
β β’ Material-UI β β β’ REST API β β β’ Load Balancer β
β β’ TypeScript β β β’ Authentication β β β’ Network Servicesβ
β β’ State Managementβ β β’ Real-time Data β β β’ BGP/Firewall β
βββββββββββββββββββββββ βββββββββββββββββββββββ βββββββββββββββββββββββ
- Frontend: React 18, TypeScript 4.9, Material-UI v6
- State Management: Recoil, TanStack React Query v5
- Routing: React Router v7
- Styling: Emotion, MUI System
- Build Tools: React Scripts (CRA), Docker, Kubernetes
- Testing: Vitest (unit + backend-contract), Playwright (E2E)
- Internationalization: i18next (ko / en / ja)
Just want a working system? Don't start here. The recommended production deployment (this UI + the loxilb-oam API + MySQL behind a TLS-terminating edge) is the single-node Docker Compose bundle that ships in the loxilb-oam repository β see its step-by-step operator guide. The options below run only the UI container and require an OAM backend you already operate β on their own they render a login page that cannot log in.
# Runs the published image β no checkout or build required.
# Point it at your running OAM backend; without a reachable BACKEND_URL the UI
# has nothing to talk to (see the Prerequisite note above and DEPLOYMENT.md).
docker run -d --name loxilb-ui -p 3000:8080 \
-e SSL_MODE=disabled \
-e BACKEND_URL=https://your-oam-host:8080 \
ghcr.io/loxilb-io/loxilb-ui:latest
# Access the application
# http://localhost:3000/netlox/With Compose, for HTTPS and .env-driven configuration:
git clone https://github.com/loxilb-io/loxilb-ui.git && cd loxilb-ui
cp .env.example .env # set BACKEND_URL
docker compose up -d
# https://localhost:3443/netlox/ (http://localhost:3000 redirects to it)# Install dependencies
npm install
# Create environment file
cp .env.example .env.local
# Start development server
npm startFull deployment guide: DEPLOYMENT.md. It covers the recommended unified management-plane bundle (Caddy edge + OAM + database in one stack) alongside the standalone Docker and Kubernetes options summarized below. For the image itself β contents, environment surface, signature verification, building your own β see docs/container-image.md.
The published image is ghcr.io/loxilb-io/loxilb-ui, tagged with the release
version (v0.9.8.7, in lockstep with loxilb and loxilb-oam). Pin a version
tag in production; :latest is a lab convenience.
docker-compose.yml runs the published image; each mode is an overlay on it.
cp .env.example .env # set BACKEND_URL
docker compose up -d- Access: https://localhost:3443/netlox/
- Features: certificate generated at start, HTTPβHTTPS redirect
- Best for: development, testing
docker compose -f docker-compose.yml -f docker-compose.http.yml up -d- Access: http://localhost:3000/netlox/
- Features: no TLS in the container β terminate it at your own edge
- Best for: behind an ingress or load balancer
mkdir -p ssl
cp your-certificate.pem ssl/cert.pem
cp your-private-key.pem ssl/key.pem
chmod 644 ssl/*.pem # readable by uid 101 inside the container
docker compose -f docker-compose.yml -f docker-compose.commercial.yml up -d- Access: https://localhost:3443/netlox/
- Features: your own certificates; the container refuses to start if they are missing or mismatched
- Best for: production
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
# or: make build-imageConfiguration is read from .env at container start β see
.env.example and the
configuration reference:
SSL_MODE=enabled # disabled | enabled | commercial
BACKEND_URL=https://oam.example.com:8080 # nginx proxies /api/oam/* β $BACKEND_URL/oam/*
BACKEND_TLS_VERIFY=off # on, once the backend has a trusted cert
FRONTEND_URL=http://localhost:3000
PUBLIC_PATH=/netlox
UI_TAG=v0.9.8.7 # pin a release- Port 3000 (host): HTTP access β redirects to HTTPS when TLS is enabled
- Port 3443 (host): HTTPS access
- Inside the container nginx listens on 8080/8443: it runs as an
unprivileged user (uid 101) and cannot bind privileged ports. Publish them
wherever you like β
-p 80:8080works fine.
- Kubernetes 1.20+
- kubectl configured
- Container registry access
# Apply all manifests (kustomize β k8s/ contains a kustomization.yaml)
kubectl apply -k k8s/
# Or deploy step by step
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml- 3 replicas with rolling updates
- Pod Disruption Budget for availability during maintenance
- Health checks (liveness and readiness probes)
- Security contexts with non-root user
- Read-only root filesystem where possible
- Capability dropping for minimal privileges
# Generate TLS secret for ingress
./k8s/generate-tls-secret.sh
# Or manually create with your certificates
kubectl create secret tls loxilb-ui-tls \
--cert=your-cert.pem \
--key=your-key.pem \
-n loxilb-system- Health endpoints at
/health - Resource limits and requests configured
# Use kustomize for environment-specific configurations
kubectl apply -k k8s/Set by SSL_MODE; full details in
docs/container-image.md β TLS modes.
- Auto-generated on container startup (365 days,
CN=localhost) - Browser warnings are normal β proceed, or trust the certificate locally
- Regenerate:
docker exec <container> /usr/local/bin/ssl-setup.sh self-signed, then restart the container
-
Prepare certificates:
mkdir -p ssl cp your-certificate.pem ssl/cert.pem cp your-private-key.pem ssl/key.pem chmod 644 ssl/*.pem # readable by uid 101 inside the container
-
Deploy with your certs:
docker compose -f docker-compose.yml -f docker-compose.commercial.yml up -d
The container refuses to start if the pair is missing or mismatched, rather than silently falling back to a self-signed certificate.
- TLS 1.2/1.3 only, forward-secret AEAD cipher suites
- HSTS on the TLS listener (never advertised over plain HTTP)
- Security headers: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, CSP
- HTTPβHTTPS redirects that honour the request's
Host - No wildcard CORS: the API is proxied same-origin, so CORS never applies
# Available commands (run against a live container)
docker exec <container> /usr/local/bin/ssl-setup.sh validate # Check the pair, print details
docker exec <container> /
2819
usr/local/bin/ssl-setup.sh self-signed # Regenerate a dev certificate- Node.js 22.x (matches CI; use
npm cifor exact locked deps) - npm
- Git
git clone <repository-url>
cd loxilb-ui
npm install# Copy example environment file
cp .env.example .env.local
# Edit with your configuration
vim .env.localnpm start # Start development server (HTTP) against .env.development
npm run build # Build for local environment
npm test # Run unit + backend-contract tests (Vitest)
npm run typecheck # TypeScript check (tsc --noEmit)
npm run e2e # Run the Playwright E2E suite (needs a live testbed β see docs/E2E_RUNNING.md)src/
βββ components/ # Reusable UI components
β βββ input/ # Form components
β βββ table/ # Data grid components
β βββ modal/ # Dialog components
β βββ layout/ # Layout components
βββ pages/ # Route-based page components
βββ hooks/ # Custom React hooks
βββ connector/ # API integration layer
βββ types/ # TypeScript type definitions
βββ locales/ # Internationalization
βββ assets/ # Static assets
- Components: PascalCase.tsx
- Hooks: camelCase.ts with
useprefix - Types: In
E3A7
terfaces start with
Iprefix - Functions: camelCase
- Constants: UPPER_SNAKE_CASE
.env.local- Local development.env.development- Development environment.env.production- Production environment
See .env.example for the full, annotated list. The build-time
(REACT_APP_*) variables the app actually reads:
# OAM API base URL. OAM serves its routes under /oam β the two modes differ by
# one path segment, so mixing them up 404s every request:
# - Development (npm start): NO proxy runs β use the DIRECT OAM base ending in
# /oam, e.g. http://<oam-host>:8080/oam (NOT /api/oam)
# - Production (deployed edge): keep the same-origin proxied path /api/oam. The
# edge β Caddy in the recommended loxilb-oam bundle, or nginx in the
# standalone UI container β rewrites /api/oam/* β <backend>/oam/*
REACT_APP_API_URL=/api/oam
# Public URL prefix the app is served under
REACT_APP_PUBLIC_URL=/netlox
# Environment name: local | production
REACT_APP_ENV=local
# Dev server
PORT=3000 # Development server port
HTTPS=false # npm start pins HTTPS=false; run react-scripts directly to serve HTTPSThese configure the standalone UI container (its built-in nginx edge). The
recommended loxilb-oam Compose bundle
does not use these β its Caddy edge is configured with SITE_ADDRESS /
EDGE_TLS / OAM_UPSTREAM instead (see that bundle's .env.example). Both
edges expose the same browser path, /api/oam/*, and rewrite it to the OAM
/oam/* routes.
SSL_MODE=enabled # disabled | enabled | commercial
BACKEND_URL=https://oam.example.com:8080 # OAM API base; nginx proxies /api/oam/* β $BACKEND_URL/oam/*
BACKEND_HOST= # Host header / SNI; derived from BACKEND_URL when empty
BACKEND_TLS_VERIFY=off # on = verify the backend's certificate chain
FRONTEND_URL=http://localhost:3000 # Browser-facing origin, forwarded to OAM as Origin
PUBLIC_PATH=/netlox # Path prefix the SPA is served under
HTTP_PORT=8080 # Container listen ports (not the published ones)
HTTPS_PORT=8443
HTTPS_REDIRECT_PORT= # Port to keep in the HTTPβHTTPS redirect (Compose sets 3443)Every value is read at container start. The two build-time exceptions β
REACT_APP_API_URL and REACT_APP_PUBLIC_URL β are inlined into the JS bundle
by Create React App, so they are properties of the image; changing the path
prefix means rebuilding. Full table:
docs/container-image.md β Environment surface.
- JWT tokens issued by the OAM login endpoint
- Server-side session revocation on logout; expired/unauthorized responses redirect to login
- RBAC β the connector gates mutating requests by role (admin / operator / viewer)
// Requests target the OAM base, which proxies to the LoxiLB gateway.
const api = {
baseURL: process.env.REACT_APP_API_URL, // e.g. /api/oam or https://oam.example.com/oam
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
}- Global error interceptor
- User-friendly error messages
- Automatic retry for network failures
- Loading states with React Query
| Command | Description |
|---|---|
npm start |
Start development server (HTTP) |
npm run build |
Build for local environment |
npm run build:dev |
Build for development environment |
npm run build:prod |
Build for production environment |
npm test |
Run unit + backend-contract tests (Vitest) |
npm run typecheck |
TypeScript check (tsc --noEmit) |
npm run e2e |
Playwright end-to-end browser suite (needs a live testbed) |
npm run e2e:cicd |
Just the cicd scenario E2E suite (tests/cicd/**) |
npm run gen:api |
Regenerate API types from api-spec/* |
npm run api:check-mapping |
Verify every connector call exists in the backend specs |
npm run sync:specs |
Re-vendor backend specs from sibling repos |
The API type-safety and backend-compatibility checks above are described in
CONTRIBUTING.md; running the end-to-end browser suite is
covered in docs/E2E_RUNNING.md.
- Code splitting with React.lazy()
- Tree shaking for minimal bundle size
- Asset optimization and compression
| Command | Purpose |
|---|---|
make docker-build |
Build the container image, stamped with package.json's version |
make build-image |
Same, tagged loxilb-ui:latest for local Compose/Kubernetes use |
make version |
Print the release this tree builds as |
./deploy.sh [http|https|commercial] [up|down|restart|logs|status] |
Drive the standalone Compose stack |
k8s/deploy.sh |
Apply the Kubernetes manifests |
# Check certificate status
docker exec <container> /usr/local/bin/ssl-setup.sh validate
# Regenerate self-signed certificates
docker exec <container> /usr/local/bin/ssl-setup.sh self-signed
docker compose restart# Check container logs β the startup banner prints the resolved BACKEND_URL,
# and warns loudly when it is unset.
docker compose logs loxilb-ui
# API calls returning 502 means the container is up but cannot reach OAM.
# Verify backend connectivity from inside the container ($BACKEND_URL must
# expand inside the container, hence the sh -c):
docker exec <container> sh -c 'curl -fsS "$BACKEND_URL/oam/health"'# Clear and reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# Check TypeScript errors
npx tsc --noEmit# Application health
curl http://localhost:3000/health
# HTTPS health (with self-signed cert)
curl -k https://localhost:3443/health- React Developer Tools - Component tree inspection
- React Query DevTools - Server state debugging
- Browser Console - JavaScript errors and network issues
- Network Tab - API request/response analysis
All changes land through pull requests β direct pushes to main are disabled, every PR needs an
approving review from a maintainer (see .github/CODEOWNERS) and green CI, and
commits must be DCO-signed (git commit -s). The full policy β
development setup, coding conventions, and the requirements to merge β is in
CONTRIBUTING.md; project roles and decision-making are in
GOVERNANCE.md.
- Fork the repository
- Create feature branch:
git checkout -b feature/description - Make changes following code guidelines
- Test thoroughly across different environments
- Submit pull request with clear description
feat: add load balancer SSL termination
fix: resolve authentication token expiry issue
docs: update deployment documentation
style: fix code formatting issues
refactor: improve component architecture
test: add unit tests for SSL configuration
- Code follows TypeScript and React best practices
- Components are properly typed
- Error handling is implemented
- Responsive design is tested
- SSL configurations work in all modes
- Docker and Kubernetes deployments tested
# Type check
npm run typecheck
# Unit + backend-contract tests
npm test
# Verify connector calls map to the vendored backend specs (H4 guard)
npm run api:check-mapping
# End-to-end browser suite (needs a live testbed β see docs/E2E_RUNNING.md)
npm run e2eThese are the same gates CI runs (
.github/workflows/ci.yml):typecheck,gen:api:check,api:check-mapping,test, and a production build.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- Deployment Guide β Docker, Kubernetes, and the unified management-plane bundle
- Contributing Guide β how to build, test, and submit changes (incl. DCO sign-off)
- Governance β project governance and decision-making
- Maintainers β current maintainers
- Code of Conduct β community standards
- Changelog β notable changes per release
- Security Policy β reporting vulnerabilities
- E2E Test Guide β running the Playwright browser suite
- SSL/HTTPS Configuration β certificate modes (in this README)
- Kubernetes Manifests β production-ready Kubernetes deployment
- React Documentation
- Material-UI Documentation
- LoxiLB Official Documentation
- Docker Documentation
- Kubernetes Documentation
Note: This dashboard is designed to work with LoxiLB load balancer infrastructure. Ensure your LoxiLB OAM API is accessible and properly configured before deployment.
For support and questions, please open an issue in the repository or consult the documentation.