Platform: Web UI

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) │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

InstallationPrerequisites

  • Go 1.25+

  • Node.js 18+ and npm

  • NATS server (optional, for multi-node deployments)

Building the WebUI

cd webuinpm installnpm run build

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:

cp -r webui/out /opt/gslb/webui

Configure gslbd to serve the WebUI:

api: enabled: true listenAddr: "0.0.0.0" port: 8080 webuiPath: "/opt/gslb/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

ConfigurationEnvironment 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.tsinterface 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.tsexport 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>

DevelopmentRunning the WebUI in Development

cd webuinpm installnpm run dev

The WebUI will be available at http://localhost:3000/ui/ (note the /ui/ path, required by basePath). Configure the API URL:

NEXT_PUBLIC_API_URL=http://localhost:8080 npm run dev

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

TroubleshootingWebSocket Connection Issues

  1. Ensure the server is running with WebSocket support

  2. 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.

  3. Check that the JWT token from /api/v1/ws/token is valid and not expired (default TTL: 24 hours)

  4. Verify network connectivity between client and server

  5. Check browser console for specific error messages

Authentication Issues

  1. 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.

  2. Verify GSLB_API_KEY and/or GSLB_WS_SECRET are set on the server. If GSLB_WS_SECRET is unset, it falls back to GSLB_API_KEY. Set GSLB_WS_SECRET explicitly for production.

  3. Ensure the token hasn't expired (default: 24 hours)

  4. Check that the Authorization header is correctly formatted for REST calls

Real-time Updates Not Working

  1. Confirm WebSocket connection is established (check connection indicator in the top-right of the sidebar)

  2. Single-node deployments (no NATS) broadcast health changes directly from the health checker sink — no NATS configuration is required

  3. Multi-node deployments require NATS: verify state.nats.servers is set and the NATS connection is established

  4. Check server logs for WebSocket or health bridge errors

Security Considerations

  • Always use HTTPS in production

  • Set a strong GSLB_API_KEY and GSLB_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


Was this article helpful?