Rename maglev-frontend → maglevd-frontend; v0.9.1; API RX/TX pulse

Rename the web dashboard binary to maglevd-frontend and move it to
/usr/sbin (it's a daemon and belongs with maglevd). The systemd unit
name stays vpp-maglev-frontend.service since that prefix is the
package name. Manpage, README, user-guide, and debian packaging all
updated in lockstep; bump to 0.9.1 for the first real release.

All frontend env vars are now prefixed MAGLEV_FRONTEND_ so a single
/etc/default/vpp-maglev can be shared with maglevd without collisions.
Every flag has an env equivalent for Docker use. MAGLEV_FRONTEND_USER
and MAGLEV_FRONTEND_PASSWORD still gate the /admin surface.

VPPInfoPanel now pulses "API: ↑↓" indicators in the zippy title
whenever a vpp-api-send / vpp-api-recv log event arrives on the SSE
stream for the scoped maglevd — 250ms blue flash, re-triggerable,
with the two arrows tightly kerned via negative letter-spacing.
This commit is contained in:
2026-04-13 00:13:47 +02:00
parent 1191b3d994
commit 35643fd774
20 changed files with 380 additions and 83 deletions

251
docs/maglevd-frontend.8 Normal file
View File

@@ -0,0 +1,251 @@
.TH MAGLEVD\-FRONTEND 8 "April 2026" "vpp\-maglev" "System Administration"
.SH NAME
maglevd\-frontend \- web dashboard for one or more running maglevd instances
.SH SYNOPSIS
.B maglevd\-frontend
\fB\-server\fR \fIaddr\fR[,\fIaddr\fR...]
[\fB\-listen\fR \fIaddr\fR]
[\fB\-log\-level\fR \fIlevel\fR]
[\fB\-version\fR]
.SH DESCRIPTION
.B maglevd\-frontend
is a single\-binary web dashboard that connects to one or more running
.BR maglevd (8)
instances over gRPC and renders a live view of frontends, backends,
health checks, and VPP load\-balancer state. The SolidJS SPA is
embedded into the Go binary via
.BR embed.FS ,
so no runtime file dependencies are required; pointing the binary at
one or more maglevds with
.B \-server
is enough to serve the dashboard.
.PP
For each configured maglevd,
.B maglevd\-frontend
maintains:
.IP \(bu 2
A long\-lived
.B WatchEvents
gRPC stream subscribed at
.BR log_level=debug ,
which delivers backend transitions, frontend transitions, per\-probe
log records (used to drive the live probe heartbeat), and per\-mutation
VPP LB sync records so the UI reflects every dataplane change in real
time.
.IP \(bu 2
A 30\-second refresh loop that re\-fetches
.BR ListFrontends / GetFrontend ,
.BR ListBackends / GetBackend ,
.BR ListHealthChecks / GetHealthCheck ,
and
.B GetVPPInfo
as a safety net against missed events.
.IP \(bu 2
A 5\-second health probe that surfaces maglevd connection drops
quickly and flips the scope\-selector indicator dot red.
.PP
Browsers connect to
.B maglevd\-frontend
over HTTP. State is hydrated once via REST and then kept live via a
Server\-Sent Events stream. Short SSE disconnects (nginx idle timeout,
wifi flap, laptop wake) are handled silently via a 30\-second replay
ring buffer; longer outages fall through to a full refetch. The SPA
is stateless on reload so refreshing the page at any time returns a
consistent view.
.PP
The frontend exposes two base paths:
.B /view/
is the read\-only dashboard and serves without authentication;
.B /admin/
is a basic\-auth\-protected variant of the same SPA that exposes
lifecycle mutations (pause / resume / enable / disable a backend,
set configured weight within a pool). The admin surface is only
mounted when both
.B MAGLEV_FRONTEND_USER
and
.B MAGLEV_FRONTEND_PASSWORD
are set to non\-empty values at startup; otherwise
.B /admin/
returns 404 and the SPA hides the admin\-toggle button entirely.
.SH OPTIONS
Each flag may also be supplied via an environment variable (shown in
parentheses); the flag takes precedence when both are set. All env
vars are prefixed with
.B MAGLEV_FRONTEND_
so a single env file can be shared with
.BR maglevd (8)
without variables leaking across processes.
.TP
.BI \-server " addr[,addr...]"
Comma\-separated list of maglevd gRPC addresses. Required. Each
entry is in
.I host:port
form; a short display name is derived from the hostname label (for
IP literals the full address is used).
.RI "(env: " MAGLEV_FRONTEND_SERVERS )
.TP
.BI \-listen " addr"
HTTP bind address for the dashboard.
.RI "(default: " :8080 "; env: " MAGLEV_FRONTEND_LISTEN )
.TP
.BI \-log\-level " level"
Structured\-log verbosity:
.BR debug ,
.BR info ,
.BR warn ,
or
.BR error .
Affects
.B maglevd\-frontend 's
own logs, not the log level it subscribes to on the upstream maglevd
(which is always
.BR debug
so the probe heartbeat can animate).
.RI "(default: " info "; env: " MAGLEV_FRONTEND_LOG_LEVEL )
.TP
.B \-version
Print version, commit hash, and build date, then exit.
.SH HTTP ENDPOINTS
.TP
.I /view/
Static SPA (HTML, JS, CSS, assets). Read\-only.
.TP
.I /view/api/maglevds
JSON array describing the configured maglevds and their current
connection status.
.TP
.I /view/api/state
Full JSON state snapshot for every maglevd.
.TP
.I /view/api/state/{name}
Full JSON state snapshot for a single maglevd.
.TP
.I /view/api/version
Build version, commit hash, and build date, plus an
.B admin_enabled
flag the SPA uses to decide whether to show the admin toggle.
.TP
.I /view/api/events
Server\-Sent Events stream. Long\-lived HTTP/1.1 chunked response
fanning out log, backend, frontend, maglevd\-status, and vpp\-status
events to every connected browser. Supports
.B Last\-Event\-ID
replay from a 30\-second / 2000\-event ring buffer, plus a
.B resync
control event emitted after every maglevd config reload so the SPA
re\-hydrates from the now\-fresh server cache.
.TP
.I /healthz
Liveness endpoint; returns 200 if the HTTP server is up.
.TP
.I /admin/
SPA shell served behind basic auth when
.B MAGLEV_FRONTEND_USER
and
.B MAGLEV_FRONTEND_PASSWORD
are configured. Returns 404 when they're not.
.TP
.I "/admin/api/{maglevd}/backend/{name}/{action}"
Backend lifecycle POST. Action is
.BR pause ", " resume ", " enable ", or " disable .
Returns the fresh backend snapshot as JSON.
.TP
.I "/admin/api/{maglevd}/frontend/{fe}/pool/{pool}/backend/{name}/weight"
Weight change POST. Body is
.B {"weight": 0\-100, "flush": bool} .
Returns the fresh frontend snapshot as JSON.
.SH REVERSE PROXY NOTES
The SSE stream has a handful of operational requirements that every
reverse proxy must satisfy:
.IP \(bu 2
Disable buffering on the events endpoint. Nginx honours
.B X\-Accel\-Buffering: no
(sent by
.BR maglevd\-frontend )
but a global
.B proxy_buffering off;
in the server block is the more robust answer.
.IP \(bu 2
Raise
.B proxy_read_timeout
to at least
.BR 300s
so the stream isn't torn down between the 15\-second
.B :\ ping
heartbeats that
.B maglevd\-frontend
sends.
.IP \(bu 2
Do not wrap the events endpoint in a gzip/brotli middleware — response
compression buffers until its window fills and destroys the live\-stream
property.
.SH ENVIRONMENT
All environment variables are prefixed with
.B MAGLEV_FRONTEND_
so this daemon can share
.I /etc/default/vpp-maglev
(or a container env file) with
.BR maglevd (8)
— whose env vars use only the shorter
.B MAGLEV_
prefix — without cross\-contamination.
.TP
.B MAGLEV_FRONTEND_SERVERS
Default value of
.BR \-server .
.TP
.B MAGLEV_FRONTEND_LISTEN
Default value of
.BR \-listen .
.TP
.B MAGLEV_FRONTEND_LOG_LEVEL
Default value of
.BR \-log\-level .
.TP
.B MAGLEV_FRONTEND_USER
HTTP basic\-auth username for
.BR /admin/ .
When set together with
.B MAGLEV_FRONTEND_PASSWORD
the admin surface is enabled; when either is missing or empty the
admin surface is hidden entirely (the SPA doesn't render the admin
toggle button and
.B /admin/
itself returns 404).
.TP
.B MAGLEV_FRONTEND_PASSWORD
HTTP basic\-auth password for
.BR /admin/ .
See
.B MAGLEV_FRONTEND_USER
above.
.TP
.B MAGLEV_FRONTEND_ARGS
Extra command\-line arguments picked up by the systemd unit's
.B ExecStart
line. Not read directly by the process — the unit expands it before
exec\-ing the binary.
.SH FILES
.TP
.I /etc/default/vpp-maglev
Environment file sourced by the systemd unit before starting
.BR maglevd\-frontend .
The same file is shared with
.BR maglevd (8);
the
.B MAGLEV_FRONTEND_ARGS
variable there is passed on the command line to
.BR maglevd\-frontend ,
and
.B MAGLEV_FRONTEND_USER / MAGLEV_FRONTEND_PASSWORD
are read from the process environment.
.SH SEE ALSO
.BR maglevd (8),
.BR maglevc (1)
.SH "FULL DOCUMENTATION"
.PP
.RS
https://git.ipng.ch/ipng/vpp-maglev/docs/user-guide.md
.RE
.SH AUTHOR
Pim van Pelt <pim@ipng.ch>