feat(core): add control plane with REST API, WebSocket, and embedded web UI#69
Open
Evsio0n wants to merge 7 commits intoencodeous:mainfrom
Open
feat(core): add control plane with REST API, WebSocket, and embedded web UI#69Evsio0n wants to merge 7 commits intoencodeous:mainfrom
Evsio0n wants to merge 7 commits intoencodeous:mainfrom
Conversation
added 7 commits
April 12, 2026 08:15
- Add ControlPlane NyModule with REST API + WebSocket + embedded SPA - Phase 1: read-only endpoints (status, nodes, routes, neighbours, prefixes, forward, sysroutes) - Phase 2: write endpoints (reload, flush_routes) + WebSocket trace streaming - Phase 3: embedded Web UI via go:embed (vanilla JS + Pico CSS) - Dashboard with stats overview, node list, and action buttons - Pages: Nodes, Routes, Neighbours, Prefixes, Forward, Live Log - WebSocket real-time trace event viewer - 10s auto-refresh on data pages - UI served at /ui/, root / redirects to /ui/ - Non-fatal bind failure (control plane is optional)
- Add Topology page with vis.js Network interactive graph - Router nodes: gold dots, Client nodes: blue triangles, Self: green diamond - Edges show metric, inferred routes shown as dashed lines - Physics-based layout with drag/zoom/hover tooltips - Legend and navigation buttons included
…ries
- Control plane now also listens on mesh interface IP (port 58175)
so other nylon nodes can query the API through the mesh tunnel
- New /api/v1/topology endpoint: BFS traversal across mesh, querying
each node's /api/v1/status + /api/v1/neighbours via mesh network
- Produces complete {nodes, edges} graph with metrics for vis.js
- Frontend Topology page simplified to consume the new endpoint
- Non-fatal: mesh listener silently skipped if bind fails
NodeCfg.Addresses contains WireGuard endpoint addresses (public IPs), not mesh tunnel addresses. The mesh IP comes from NodeCfg.Prefixes (e.g. 10.114.154.11 from prefix 10.114.154.11/32). Fixes both listenMesh and resolveNodeAddr to use Prefixes.
ControlPlane.Init() runs before the Nylon module creates the WireGuard interface, so the mesh IP doesn't exist yet. Changed to a goroutine that retries binding every second for up to 30 attempts.
Babel uses uint32 max as infinity meaning unreachable. Don't draw edges for these — still add the node to the graph but skip the connection.
- Remove topology from 10s auto-refresh cycle - Add Refresh button with loading state and node/link count - Fade-in animation when topology data loads (PJAX-like feel) - Status text shows loading state and result summary
Owner
|
Hi, this is very cool! I love to see people building on nylon. However, I think this can be a separate project, since it has its own scope and maintenance needs, and is not critical for the functionality of nylon. I think a feasible way is to interact with nylon over the built-in (wireguard-compatible) IPC mechanism:
I think this contribution is great, and it is something that I would appreciate as well, let me know what you think. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a full-featured control plane module to nylon with a REST API, WebSocket real-time log streaming, and an embedded web UI (SPA) for mesh network monitoring and management.
Phases
Phase 1 — Read-only REST API
/api/v1/status— node identity and role/api/v1/nodes— all mesh participants/api/v1/routes— Babel route table/api/v1/neighbours— neighbour links with endpoint/metric details/api/v1/prefixes— advertised prefixes/api/v1/forward— kernel forwarding table/api/v1/sysroutes— system route tablePhase 2 — Write Operations & WebSocket
POST /api/v1/reload— trigger config reloadPOST /api/v1/flush_routes— flush Babel routesWS /api/v1/ws— real-time packet trace streamPhase 3 — Embedded Web UI
go:embedfor static assets, no external file serving neededTopology Aggregation
127.0.0.1:58175and mesh prefix address (e.g.10.114.154.11:58175)/api/v1/topologyperforms BFS across mesh: queries each node's/status+/neighboursvia mesh network, producing a complete{nodes, edges}graphFiles Changed
core/control_plane.go(+852) — REST API, WebSocket, topology aggregation, mesh listenercore/entrypoint.go(+1) — register ControlPlane modulecore/ui/index.html(+189) — SPA shellcore/ui/app.js(+469) — SPA logic, vis.js topology renderingcore/ui/style.css(+263) — dark theme, topology canvas, animationsDesign Decisions