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:
251
docs/maglevd-frontend.8
Normal file
251
docs/maglevd-frontend.8
Normal 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>
|
||||
Reference in New Issue
Block a user