Files
Nexus-Guard-Suite/.sisyphus/plans/nxg-wgdashboard-config-parity.md
T
datadunia bf9cbba535 feat: complete WGDashboard config parity
Backend (server-core):
- Extend firewall NetManager with AddForwardRule, AddInputRule via nft CLI
- Sync FORWARD rules on peer create, update, delete, suspend/unsuspend
- Sync INPUT rules on server create, update (port change), delete
- Fix duplicate import and missing firewall cleanup calls

Frontend (dashboard-ui):
- Add Edit Node modal for MTU, DNS, ListenPort configuration
- Add Advanced Peer Settings accordion (AllowedIPs, DNS, MTU, Keepalive, Notes)
- Add Suspend/Unsuspend toggle with SUSPENDED badge
- Update API client for new endpoints and fields
2026-05-22 02:27:04 +07:00

8.0 KiB

Plan: WGDashboard Config Parity (Phase 5.5)

1. Goal

Achieve feature parity with WGDashboard for WireGuard configuration editing and peer settings, adapting WGDashboard's local-file management approach to NexusGuard's multi-node database-driven SD-WAN architecture.


2. Current Status (May 22, 2026)

COMPLETED

Phase 1: Database Model Updates (Backend)

  • Update WgServer Model: Added MTU (default 1420), DNS (default "1.1.1.1").
  • Update Device Model: Added EndpointAllowedIPs, DNS, MTU, PersistentKeepalive (default 25), Notes, IsSuspended, RxBytes, TxBytes.
  • Database Migration: Auto-migrate via GORM AutoMigrate.

Phase 2: API Updates (Backend)

  • Server API (servers.go): PUT /api/v1/servers/:id — pointer fields for partial updates, firewall sync on port change.
  • Device API (devices.go): PUT /api/v1/devices/:id — pointer fields for EndpointAllowedIPs, DNS, MTU, PersistentKeepalive, Notes.
  • Config Generation (peers.go): getDeviceConfig — DNS override (device > server > "1.1.1.1"), MTU override, PersistentKeepalive, EndpointAllowedIPs.
  • Peer Suspension API: POST /api/v1/devices/:id/suspend and /unsuspend with IsSuspended toggle + firewall rule add/remove.

Phase 3: Firewall Enforcement Sync (nftables) — MOSTLY DONE

  • Firewall Manager Interface: Extended with AddForwardRule, RemoveForwardRule, AddInputRule, RemoveInputRule.
  • Linux Implementation: nftables_linux.go via nft CLI (AddForwardRule, RemoveForwardRule, AddInputRule, RemoveInputRule).
  • Stub Implementation: nftables_stub.go for non-Linux builds.
  • Server Create: AddInputRule(server.Name, server.ListenPort) in servers.go.
  • Server Update: Firewall re-sync when ListenPort changes in servers.go.
  • Server Delete: RemoveInputRule(server.Name) in servers.go.
  • Peer Suspend: RemoveForwardRule / AddForwardRule in devices.go toggleSuspension.
  • Device Delete (partial): RemoveRangeRule called but missing RemoveForwardRule.

REMAINING (to be completed now)

Phase 3: Backend Firewall Fixes

  • Fix duplicate "net" import in devices.go (lines 4-5, two imports of same package).
  • Add AddForwardRule in peers.go CreatePeer — after device creation, add FORWARD rule for device AllowedIPs.
  • Add firewall sync in devices.go Update — when EndpointAllowedIPs or AllowInternet changes, re-sync FORWARD rule.
  • Add RemoveForwardRule in devices.go Delete — clean up FORWARD rule when device is deleted.

Phase 4: Dashboard UI (Frontend)

  • Node Edit Modal in Servers.vue — Edit Node button + modal to configure MTU, DNS, ListenPort via PUT /api/v1/servers/:id.
  • Advanced Peer Settings in DeviceDetail.vue — Accordion section with fields for AllowedIPs, DNS, MTU, Keepalive, Notes, Suspend toggle, using new API fields.
  • Update API client (servers.ts, devices.ts) — Add updateServer(), suspendDevice(), unsuspendDevice() and extend updateDevice() with new fields.

3. Implementation Tasks

Task A: Backend Fixes (4 edits across 2 files)

A.1 devices.go — Duplicate import

  • Remove second "net" import on line 5.
  • File: apps/server-core/api/devices.go
  • Verify: go build ./... passes.

A.2 peers.go — Add ForwardRule on CreatePeer

  • After line ~131 (configText generation), add:
    // Sync firewall FORWARD rule for this peer
    h.fw.AddForwardRule(device.Name, ip, allowedIPs)
    
  • Also handle case where EndpointAllowedIPs is empty — derive from AllowInternet.
  • File: apps/server-core/api/peers.go

A.3 devices.go — Firewall sync on Update

  • In Update() handler, after device is updated, re-sync FORWARD rule if:
    • EndpointAllowedIPs changed (req.EndpointAllowedIPs != nil)
    • AllowInternet changed (req.AllowInternet != nil)
  • Calculate destCIDR from device's EndpointAllowedIPs > AllowInternet > InternalIP
  • Call h.fw.RemoveForwardRule(device.Name) then h.fw.AddForwardRule(...) with new CIDR.

A.4 devices.go — ForwardRule cleanup on Delete

  • In Delete() handler, add h.fw.RemoveForwardRule(device.Name) before or after the existing h.db.Delete(&device).
  • File: apps/server-core/api/devices.go

Task B: Frontend API Client Updates

B.1 servers.ts — Add updateServer()

export const updateServer = async (id: string, data: {
  name?: string;
  public_endpoint?: string;
  listen_address?: string;
  listen_port?: number;
  mtu?: number;
  dns?: string;
}) => {
  await api.put(`/servers/${id}`, data)
}

B.2 devices.ts — Extend updateDevice() + add suspend/unsuspend

export const updateDevice = async (id: string, data: {
  name?: string;
  allow_internet?: boolean;
  endpoint_allowed_ips?: string;
  dns?: string;
  mtu?: number;
  persistent_keepalive?: number;
  notes?: string;
}) => {
  await api.put(`/devices/${id}`, data)
}

export const suspendDevice = async (id: string) => {
  const { data } = await api.post(`/devices/${id}/suspend`)
  return data
}

export const unsuspendDevice = async (id: string) => {
  const { data } = await api.post(`/devices/${id}/unsuspend`)
  return data
}

B.3 Device interface — Add new fields

export interface Device {
  // ... existing fields ...
  EndpointAllowedIPs?: string
  DNS?: string
  MTU?: number
  PersistentKeepalive?: number
  Notes?: string
  IsSuspended?: boolean
}

Task C: Frontend UI Components

C.1 Servers.vue — Edit Node Modal

Add to the template:

  • An "Edit" button next to "Delete" in each server row
  • A modal dialog (glassmorphism style matching current design) with fields:
    • ListenPort (number input)
    • MTU (number input)
    • DNS (text input)
  • Form submits to updateServer(id, payload) API
  • Modal uses v-model="showEditModal" to open/close
  • Refresh list after update

Implementation approach:

  • Add editingServer ref to track which server is being edited
  • Add modal template with glassmorphism card (bg-gray-900/90 rounded-2xl border border-white/10 shadow-lg backdrop-blur-xl)
  • Pre-populate form with current server values
  • On submit: call API, close modal, reload list

C.2 DeviceDetail.vue — Advanced Peer Settings

Add after the AllowInternet toggle section:

  • A collapsible "Advanced Settings" accordion
  • Inside: form fields for:
    • AllowedIPs (text input - comma-separated CIDRs)
    • DNS (text input)
    • MTU (number input)
    • PersistentKeepalive (number input)
    • Notes (textarea)
    • Suspend (toggle switch with API call)
  • "Save" button calls updateDevice() with all fields
  • Suspend toggle calls suspendDevice() / unsuspendDevice() separately
  • Show "Suspended" badge when device is suspended

4. Execution Strategy

Wave 1 (parallel — backend fixes + frontend API):
├── Task A: Backend fixes (devices.go, peers.go)
├── Task B: Frontend API client updates (servers.ts, devices.ts, peers.ts)

Wave 2 (parallel — frontend UI):
├── Task C.1: Servers.vue Edit Node modal
├── Task C.2: DeviceDetail.vue Advanced Peer Settings accordion

Wave 3 (final — verification):
├── Verify go build ./... passes
├── Verify npm build passes (or at least no TS errors)
├── Update plan file with final status
├── Commit all changes

5. Verification Strategy

Backend Verification

cd apps/server-core
go build ./...     # Expected: PASS (no errors)
go vet ./...       # Expected: PASS (no warnings)

Frontend Verification

cd apps/dashboard-ui
npx vue-tsc --noEmit   # Expected: PASS (no type errors)
npm run build           # Expected: PASS (build succeeds)

Manual QA (after deploy to wglab)

  • Add Node → Edit Node (change MTU, DNS, ListenPort) → Verify
  • Create Peer → Edit Advanced Settings (AllowedIPs, DNS, MTU, Keepalive, Notes) → Verify
  • Toggle Suspend → Verify peer status changes → Verify firewall rules update
  • Verify nftables rules: nft list chain ip nexusguard forward, nft list chain ip nexusguard input