WebUI Documentation¶
The GSLB WebUI is a modern Next.js-based dashboard for managing the GSLB system. It provides real-time monitoring and configuration capabilities through an intuitive interface.
Features¶
- Real-time Dashboard: Live overview of all pools and their health status
- WebSocket Updates: Instant notifications when members go online/offline
- Pool Management: Create, view, and manage pools and their members
- Service Configuration: Manage DNS services and their mappings
- Health Monitoring: Visual health status with health scores and history
- Activity Feed: Live feed of health changes and configuration updates
Architecture¶
┌─────────────────────────────────────────────────────────────────┐
│ WebUI (Next.js) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Dashboard │ │ Pool Mgmt │ │ Member Health View │ │
│ │ (Real-time)│ │ (CRUD) │ │ (WebSocket) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ REST API + WebSocket
▼
┌─────────────────────────────────────────────────────────────────┐
│ gslbd (Go Backend) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ REST API │ │ WebSocket │ │ NATS/JetStream │ │
│ │ (18+ ep) │ │ Server │ │ (Real-time bridge) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Installation¶
Prerequisites¶
- Go 1.25+
- Node.js 18+ and npm
- NATS server (optional, for multi-node deployments)
Building the WebUI¶
The build output is placed in webui/out/ (static HTML export). This is the directory to deploy.
Deploying the WebUI¶
Copy the static export to your desired location:
Configure gslbd to serve the WebUI:
Accessing the WebUI¶
Once deployed, access the WebUI at:
- http://<host>:8080/ui/ - WebUI dashboard (redirected from /)
- http://<host>:8080/api/v1/ - REST API
- ws://<host>:8080/api/v1/ws - WebSocket for real-time updates
Configuration¶
Environment Variables¶
The WebUI can be configured via environment variables or defaults to relative URLs:
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_API_URL |
REST API base URL | Same origin |
NEXT_PUBLIC_WS_URL |
WebSocket URL | Same origin with ws:// protocol |
Backend Environment Variables¶
| Variable | Description | Default |
|---|---|---|
GSLB_API_KEY |
REST API authentication key | Unauthenticated |
GSLB_WS_SECRET |
WebSocket JWT signing secret | Value of GSLB_API_KEY |
GSLB_CLUSTER_ID |
Cluster identifier for NATS | default |
WebSocket Protocol¶
The WebSocket connection provides real-time updates. Connect with a JWT token obtained from /api/v1/ws/token.
Connection Example¶
const response = await fetch('/api/v1/ws/token');
const { token } = await response.json();
const ws = new WebSocket(`ws://localhost:8080/api/v1/ws?token=${token}`);
Message Types¶
| Type | Description | Payload |
|---|---|---|
health_update |
Health status change | {poolId, ipAddress, healthy, score, timestamp} |
pool_update |
Pool CRUD event | {action, pool} |
member_update |
Member CRUD event | {action, poolId, member} |
member_snapshot |
Full member data | {action, poolId, member} |
service_update |
Service CRUD event | {action, service} |
Example Messages¶
Health Update (member goes offline):
{
"type": "health_update",
"payload": {
"poolId": "pool-123",
"ipAddress": "192.168.1.1",
"healthy": false,
"score": 0.0,
"timestamp": 1234567890000,
"rttMs": 0,
"node": "node-1"
}
}
Pool Created:
{
"type": "pool_update",
"payload": {
"action": "created",
"pool": {
"id": "pool-456",
"name": "web-servers",
"createdAt": 1234567890000,
"updatedAt": 1234567890000
}
}
}
Dashboard¶
The main dashboard provides:
Stats Cards¶
- Total Pools
- Total Members
- Healthy Percentage
- Server Uptime
Pool Health Grid¶
Each pool shows:
- Pool name and ID
- Members listed as label: ip_address (or bare IP if no label is set), sorted by priority ascending then weight descending — the member most likely to receive traffic appears first
- Green/red health indicators per member
- Health scores when configured
- Real-time status updates via WebSocket
Activity Feed¶
Shows recent events: - Health status changes - Member additions/removals - Pool modifications
State Management¶
The WebUI uses Zustand for client-side state management:
// lib/store.ts
interface GSLBState {
pools: Pool[];
members: Record<string, Member[]>;
services: Service[];
healthStatus: Record<string, Record<string, MemberHealth>>;
dashboardStats: DashboardStats | null;
// ... actions
}
API Integration¶
REST API calls are handled through a centralized client:
// lib/api.ts
export async function listPools(): Promise<Pool[]>
export async function createPool(name: string): Promise<Pool>
export async function getPoolStatus(poolId: string): Promise<PoolStatus>
export async function getSnapshot(): Promise<SnapshotResponse>
export async function getDashboardStats(): Promise<DashboardStats>
Development¶
Running the WebUI in Development¶
The WebUI will be available at http://localhost:3000/ui/ (note the /ui/ path, required by basePath). Configure the API URL:
Tech Stack¶
- Framework: Next.js 14+ (App Router)
- UI: React 18+, Tailwind CSS
- State: Zustand
- Data Fetching: TanStack Query (React Query)
- Charts: Recharts (optional)
- Icons: Lucide React
Project Structure¶
webui/
├── src/
│ ├── app/ # Next.js app router pages
│ │ ├── layout.tsx # Root layout with sidebar
│ │ ├── page.tsx # Dashboard
│ │ ├── pools/ # Pool management pages
│ │ └── providers.tsx # React Query provider
│ ├── components/
│ │ ├── dashboard/ # Dashboard components
│ │ │ ├── StatsCards.tsx
│ │ │ ├── PoolHealthGrid.tsx
│ │ │ └── RecentActivity.tsx
│ │ ├── layout/
│ │ │ └── Sidebar.tsx # Navigation sidebar
│ │ └── ui/ # Reusable UI components
│ │ ├── LoadingSpinner.tsx
│ │ └── ErrorDisplay.tsx
│ └── lib/
│ ├── api.ts # REST API client
│ ├── types.ts # TypeScript definitions
│ ├── websocket.ts # WebSocket hook
│ └── store.ts # Zustand store
├── .env.production # Production environment
├── next.config.js
├── package.json
└── tailwind.config.ts
Troubleshooting¶
WebSocket Connection Issues¶
- Ensure the server is running with WebSocket support
- The WebSocket endpoint (
/api/v1/ws) is auth-exempt in the HTTP middleware; authentication is handled by the JWT token in the query string (?token=<jwt>). If you see 401s on the WS endpoint, confirm you are running a patched build. - Check that the JWT token from
/api/v1/ws/tokenis valid and not expired (default TTL: 24 hours) - Verify network connectivity between client and server
- Check browser console for specific error messages
Authentication Issues¶
- The REST API uses
Authorization: Bearer <token>(HTTP header). The WebSocket endpoint uses?token=<jwt>(query string) — these are different mechanisms; do not mix them. - Verify
GSLB_API_KEYand/orGSLB_WS_SECRETare set on the server. IfGSLB_WS_SECRETis unset, it falls back toGSLB_API_KEY. SetGSLB_WS_SECRETexplicitly for production. - Ensure the token hasn't expired (default: 24 hours)
- Check that the Authorization header is correctly formatted for REST calls
Real-time Updates Not Working¶
- Confirm WebSocket connection is established (check connection indicator in the top-right of the sidebar)
- Single-node deployments (no NATS) broadcast health changes directly from the health checker sink — no NATS configuration is required
- Multi-node deployments require NATS: verify
state.nats.serversis set and the NATS connection is established - Check server logs for WebSocket or health bridge errors
Security Considerations¶
- Always use HTTPS in production
- Set a strong
GSLB_API_KEYandGSLB_WS_SECRET - Consider firewall rules to restrict API access
- JWT tokens expire after 24 hours by default
- Audit log all API mutations via
GSLB_AUDIT_LOG