Releases: InfoDiveLabs/trinetra
Release list
v0.5.0 - fleet mode, signed self-update
The first release since the serverwatch rename, and the biggest yet: fleet
mode (master/child, phases 1-3 -- replication and local fallback, a full
alerting/incidents/routing engine, and a fleet web UI), signed releases with
a maintainer-verified, self-rolling-back update path, and a round of web UI
polish, all documented in a new security chapter.
Releases are Linux-only from this version on; v0.4.1 was the last to also
ship macOS (darwin) binaries. The license also changes, see below.
Added
- Fleet mode (master/child), phase 1. A master enrolls children with a
one-line join code that pins its CA (no trust-on-first-use); children then
talk to it over mutual TLS with 90-day client certificates that renew
themselves, and can be revoked. Each child spools a copy of its samples, down
events and alert log into a durable, capped outbox and ships it to the
master, which keeps a per-node replica. A master outage loses nothing: the
backlog drains in order when it returns, and if the outbox cap was hit the
dropped range is rebuilt from the child's local store before newer data is
sent. The master raises node-down alerts (folded into one fleet-connectivity
alert when most of the fleet drops at once); a child warns locally when its
link has been down for ten minutes. trinetra fleetcommands:init,join,leave,disable,
status,nodes,node revoke|rename|tag, andtoken create|list|delete.
See the command reference.- Config keys
fleet.listen(default:9443),fleet.outbox_max_mb
(default512) andfleet.node_down_after(default2m). The role and
identity keys are managed bytrinetra fleetand refused byconfig set. - Control socket: requests take an optional
nodeto read a remote node's
replica through the same methods, plus newFleet.*methods for fleet
management. Both are backward compatible: requests withoutnodebehave as
before. - Fleet mode, phases 2 and 3: fleet alerting and the fleet web UI. The
master now decides delivery for the whole fleet instead of just relaying
node-down alerts. A child holding a valid lease routes its firing alerts to
the master instead of delivering them itself, and falls back to local
delivery (prefixed "via local fallback") if no receipt arrives within
fleet.fallback_afteror the lease expires -- at-least-once, deduplicated
by(node, alert key, fired_at), never doubled up. On the master, every
alert runs through a full pipeline -- silence, dependency fold, grouping,
routing, escalation, delivery, receipt -- all recorded and explainable with
fleet explain. New: ordered routes with matchers andcontinuefan-out
to several escalation policies at once; multi-step escalation policies with
repeat_every; silences and recurring maintenance windows (matched by tag,
node name-glob-or-id, rule, and severity, and pushed to children so local
fallback honours them too); incident grouping and dependency folding;
fixed-grammar aggregate rules (count,avg/max/min,online,
absent) evaluated fleet-wide on the master; and managed config, a closed
10-key allowlist a master can push to children by tag, read-only locally
and re-imposed on every apply. The master's Telegram messages gain Ack and
Silence-1h inline buttons on incident fire notifications. Newtrinetra fleetsubcommands:incidents,incident,ack,explain,silence add|list|expire,maintenance add|list|delete,route test,alerting show|apply,rules,managed list|set|delete|status, andnode depends.
New config keysfleet.fallback_after(default2m) and
fleet.link_down_warn_after(default10m), both child-only and
live-applied. See Fleet
alerting. - The fleet web UI. Every existing page is now also reachable per node
under/n/{id}/..., with a replica banner and a stale-data indicator for
remote pages, a top-bar node switcher, and a Ctrl/Cmd-K fuzzy palette
(recent nodes, and a "web1 history"-style page-type jump)./fleetgains a
health strip, a heatmap, top-N panels, a sortable/filterable live node
table, and a compare view (up to 10 nodes, or an aggregate, one metric
overlaid). New admin pages:/fleet/admin(tokens, node rename/tags/
dependencies/revoke/remove, link health),/fleet/incidents(list and
timeline, with ack/silence),/fleet/alerting(routes/policies/rules
editor plus a route tester),/fleet/silences(silences and maintenance
windows, times shown in the master's own local zone),/fleet/managed
(managed-config fragments and per-node drift), and/fleet/audit(every
fleet mutation, who and when). Remote-node actions (ack/unack, container
logs) work whenever that node is currently connected, and are disabled
with a reason when it isn't. See The web
UI. - Signed self-update.
trinetra update status|check|apply|rollback
fetches, independently verifies (CI signature + maintainer co-signature
over a manifest of exact file hashes), stages, smoke-tests and swaps in a
new release, then launches a guarded restart that confirms the new build
is healthy within 90s or automatically rolls back and marks the version
bad.trinetra install --require-signedruns the same signature check for
the initial install. New config keysupdate.channel(defaultstable),
update.source(defaultgithub),update.github_token, and
update.check_interval(default24h); the daemon checks on that cadence
and alerts when an update becomes available, commits, or rolls back.
Releases are Linux-only: from this release on, macOS (darwin) binaries
are dropped (v0.4.1, as serverwatch, was the last release to ship them).
Maintainer tooling (cmd/trinetra-release) and the key ceremony/release
process are documented in Operations: Release keys and releasing.
See Operations: Updating.
Changed
- Renamed to Trinetra. serverwatch is now Trinetra ("Sees what you
can't."): modulegithub.com/InfoDiveLabs/trinetra, binariestrinetra,
trinetra-ctl,trinetra-web, paths/etc/trinetra,/var/lib/trinetra,
/run/trinetra, and thetrinetra.serviceunit. The web UI, TUI, and
notifications carry the new Trinetra visual identity. The GitHub repo moves
toInfoDiveLabs/trinetra(the oldSuraj-Tiwari/server-monitorURLs
redirect).- Upgrade: download
trinetraand the plugins you use
(trinetra-ctl,trinetra-web) into one directory, then run the one
command you already know,sudo trinetra install. On a host with an existing serverwatch install it detects it
and migrates in place before the normal install runs: it stops and
disablesserverwatch.service, moves/etc/serverwatch→
/etc/trinetraand/var/lib/serverwatch→/var/lib/trinetra(an
atomic rename, or a byte-verified copy when the two are on different
filesystems, so nothing is deleted before its replacement is proven in
place), rewrites any config paths that pointed inside the old
directories, then removes the old unit and plugin binaries (a drop-in
override dir for the old unit, if any, is left in place with a note) and
replaces/usr/local/bin/serverwatchwith a compat symlink to
trinetra;/usr/bin/serverwatchis deliberately left pointing at it
rather than redirected or removed, sosudo serverwatch ...still
resolves viasecure_pathon distros that omit/usr/local/bin. Both
compat names are kept for one release, with a deprecation notice on use.
It refuses rather
than merges if both a serverwatch install and existing trinetra data are
present, or a legacy directory is unexpectedly empty (likely an
unmounted volume);--state-already-at-new-pathadopts a state volume
you moved yourself,--forceproceeds past aserverwatch.service
systemd could not confirm was stopped or aserverwatch daemonstill
running outside it (found through its pid file). An old plugin with no
trinetra-ctl/trinetra-webcounterpart next totrinetrais named in
aWARNING:line of the summary. Until install has run,trinetra daemonand the config- and state-writing CLI commands refuse on a host
that has only a serverwatch install, instead of starting empty. A
/var/lib/trinetra/migrated-from-serverwatchmarker records the
migration; the whole thing is idempotent and resumable, and every stop
point explains how to finish or roll back by hand. See Upgrading from a
serverwatch install. - Kept on purpose: the web cookie names
sw_session/sw_enroll/sw_login
(renaming them would log every user out); the WebAuthn RP ID/origin
handling (config-driven, bound into existing passkeys); config JSON keys;
plugins.jsonkey names; thecontrol.sock/tokenfile names inside the
runtime dir; the/usr/local/bin/serverwatch→trinetracompat symlink
and the/usr/bin/serverwatchlink that keeps pointing at it (both
removed in the next release); the
SERVERWATCH_CONTROL_SOCKET/TOKENenvironment fallback (also removed in
the next release); and the literal"serverwatch-control"control-socket
ha...
- Upgrade: download
channels
v0.4.1 - server identity, security hardening, reliability
The stable cut of the 0.4.1-beta.1…beta.3 line, tested on the live host since 2026-08-02. Supersedes v0.4.0.
Highlights
- Server identity (#99). Configurable
server.nameacross web, ctl, and alert titles; host inventory (CPU/RAM/disks/OS/uptime) on a new web Host page,serverwatch-ctl host, andcore.API.HostInfo; local + opt-in public IP; CPU/mem alerts name the top process and container. (#100, #101, #102, #103) - Security hardening. Fail-closed control socket (#96) and web user store (#105), bounded Telegram enrollment PIN brute force (#93), DOM XSS sink removed (#94), rate-limited ceremony begins (#95), opt-in outbound SSRF guard (#97), documented plugin-copy trust assumption (#98).
- Reliability. Web dashboard no longer freezes on a desynced socket client (#105); daemon restarts no longer recorded as host downtime (#116); fail-visible collection with per-collector health and alerts (#110); Swarm services keyed by service, not task (#118); storage maintenance no longer stalls history reads (#113).
- Operability. Build-time version stamps with mismatch detection (#107); series-cardinality guardrail in
doctor(#112); setup UX fixes (#106); container logs in the drawer; paginated downtime list.
Full detail: CHANGELOG.
Binaries are stripped (-s -w -trimpath) and stamped v0.4.1; verify downloads against checksums.txt (sha256sum -c).
v0.4.1-beta.3: reliability + versions + setup UX
Five tracker issues, all with core / web / ctl parity.
Added
- Versions in the panel (#107). Build-time version stamp per binary (git-derived,
devfallback for plaingo build). The web sidebar shows the core daemon version (over the socket) and the web plugin version, with a "version mismatch" marker after a partial upgrade.serverwatch-ctl versionprints both. - Monitoring-failure alerts (#110). A collector (docker/disk/services/smart) failing for 3 consecutive cycles raises
collector:<name>and recovers on success.
Fixed
- Collection is fail-visible (#110). A failed/timed-out collection command no longer publishes missing data or flips a healthy target to gone: it carries last-known values forward (marked stale) and records the failure. Per-collector health is in
status.json, a web dashboard banner, andserverwatch-ctl status. - Swarm services keyed by service, not task (#118). On a Swarm node, containers key on the stable service name instead of the ephemeral
<service>.<slot>.<taskid>(tasks summed), so a rolling deploy makes no new per-task series and no false down/recover churn, and per-service history is continuous. Plain-docker hosts unchanged. - Cardinality guardrail (#112).
serverwatch doctorwarns when the time-series count is abnormally high (healthy is low hundreds). Stale series already age out past retention. - Setup UX (#106). The proxy-mode web wizard offers an optional domain step (derives rp_id/origin, or documents the forwarded-header assumption on confirm).
serverwatch installno longer nudges Telegram setup when a token is already configured.
Beta/preview build from develop (unstripped for field debugging). Verify with sha256sum -c checksums.txt.
v0.4.1-beta.2: security + server identity + fixes
Folds together everything since 0.4.1-beta.1: a security-hardening pass, the server-identity epic (#99), and a round of fixes from testing beta.1 on the live host. Every capability lands in core, web, and serverwatch-ctl together.
Fixed (from beta testing)
- Multi-socket CPUs report their socket count. Dual-socket boxes were reading as one CPU. Now
2x <model> (2 sockets / 32 cores / 64 threads). - Disk inventory shows only real disks. Docker
overlay,tmpfs, snapsquashfs/loop and other pseudo filesystems are filtered out; local block devices, LVM volumes, and network mounts (NFS/CIFS) are kept. - Container logs are viewable. Drawer "View logs" wired to
core.API.ContainerLogs(validateddocker logs --tailover the socket), alsoserverwatch-ctl logs <container> [--tail N]. - Per-metric history sparklines. Series-backed drawer rows (disks) draw a real 6h sparkline from
/api/series; rows without a series omit the chart. - Host strip on the dashboard (desktop): name, OS, CPU, RAM, uptime, local IP, linking to the Host page.
- Identity setup in the web UI. The
/configIdentity panel setsserver.nameand toggles thecollect.public_ipopt-in. - Downtime list paginated on the history page (8 plus "Show all").
Server identity (#99)
- Configurable
server.name(name, then hostname, thenserverwatch); web brand, ctl header/config,[name]-prefixed alert titles (#101) - Host inventory over
core.API.HostInfo(): web Host page plusserverwatch-ctl host --json(#100) - Local IP always; public IP opt-in via
collect.public_ip(#102) - CPU/RAM alerts name the top process/container culprit (#103)
Security hardening
- Control socket fails closed without its auth token (#96); web fails closed on an unreadable user store (#105); opt-in SSRF guard
notify.block_private_targets(#97); bounded Telegram enrollment PIN (#93); drawer built withtextContent(#94); rate-limited ceremony begins (#95); per-file locking so maintenance does not stall reads (#113); daemon restart no longer fabricates downtime (#116).
Beta/preview build from develop (unstripped for field debugging). Verify with sha256sum -c checksums.txt.
v0.4.1-beta.1
Preview build for the core-plus-plugin line. A reliability release: the web plugin is made truly channel-only, and a socket-client defect that could freeze the dashboard is fixed.
Fixed
- The web dashboard no longer freezes into an all-zero board until a core restart. The control-socket client held one long-lived connection with no reconnect: on a read timeout or a response-id mismatch it returned the error but kept the connection, which is then permanently frame-misaligned (a late response is read by the next call and mismatches its id, desyncing every call after). Because serverwatch-web holds one client for its whole lifetime, a single slow daemon response wedged every Snapshot and the dashboard rendered the zero-value view (0 cores, 0%, Offline) while alerts and Telegram kept working. The client now poisons the connection on any transport failure and transparently re-dials on the next call. (#105)
Changed
- The web plugin no longer reads or writes daemon-owned state on disk. Active alerts, alert history, and alert acks now go through the control socket (core.API.ActiveAlerts / AlertHistory / AckAlert) instead of decoding alerts.json / alertlog.jsonl directly, and the ack handler no longer writes alerts.json (it had been a second writer racing the daemon). The web keeps ownership of its own auth material (users, sessions, enrollment tokens); the core has nothing to do with auth.
- core.AlertRecord gains a DeliveredTo field so the alerts page's Delivered column keeps its per-channel names over the socket.
Notes
- Preview channel (unstripped, debuggable). Verified: full unit suite,
go test -raceon the control and web packages, and the stdlib-only build guard all pass. - Verify downloads with checksums.txt:
sha256sum -c checksums.txt.
v0.4.0 - core plus plugins
serverwatch v0.4.0 -- the core-plus-plugin stable release, promoted from the v0.4.0-beta.x line (validated live).
The core-plus-plugin release. serverwatch is reshaped from a single monolithic
daemon into a lean, stdlib-only serverwatch core with plugin binaries layered
around it over a local control socket. The core stays small while the web UI
and management tooling move out of process.
Added
- Control socket and
core.API. The core exposes one internalcore.API
contract over a unix socket in the runtime directory, newline-delimited JSON,
one request or response per line. Each daemon launch mints a fresh token that
a client must present in a handshake before the socket answers, keeping the
channel local and gated to processes that can read the token. serverwatch-webout of process. The passkey web UI now runs as its own
binary with no build tag, talking to the core over the socket. The core
verifies, spawns, restarts (capped backoff), and stops it as a child process
whenweb.enabledis set. The defaultserverwatchbinary is stdlib-only,
enforced by a dependency-graph test.serverwatch-ctl, the primary management client. A separate interactive
binary that dials the socket, with a styled live-status home dashboard
(colour-coded CPU/MEM/SWAP meters, a live CPU sparkline, an alerts panel, a
disks panel, a 24h availability strip, and a network/inventory line), guided
screens for schedule, quiet hours, healthchecks, monitor thresholds, and
channels, an all-settings screen over every remaining config key, a guided
web-setup wizard functional in every serving mode, first-run Telegram
onboarding, a?help overlay, and breadcrumbs.- Scriptable
serverwatch-ctlsubcommands.status,doctor, and
alertsgain--jsonoutput;config get <key>/config set <key> <value>reach every flat config key through the same validated setter the
TUI uses (applied live);channels test <name>sends a live test
notification. - Live event streaming over the control socket.
core.API.Subscriberuns
end to end: an in-process event bus that the sampler loop and every dispatched
alert publish onto, a dedicated socket connection streaming those events, and
serverwatch-websubscribing to push live dashboard updates. - Front-door install and safe-exec.
serverwatch installrecords each
plugin's checksum in a root-only manifest; theserverwatch cliand
serverwatch webfront-doors verify a plugin (owner, permissions, checksum)
against that manifest before exec'ing it. - Mobile web UI. The dashboard is fully responsive: a bottom tab bar with a
"More" sheet, card-list tables, and layouts gated to narrow viewports. - Enrollment PIN over the socket (#90).
serverwatch telegram set-token
prints the/start <pin>instruction directly to the terminal after saving
the token;serverwatch-ctl's onboarding surfaces the same PIN. - Optimized production release channel.
make release-prodbuilds stripped,
trimmed binaries (-s -w -trimpath) for the stable line, alongside the
unstrippedmake releaseused for beta/dev builds.
Changed
- The web UI no longer builds with
-tags webinside the daemon; it is a
separate supervised process. Guided setup (web UI, Telegram onboarding) is
owned byserverwatch-ctl; the core CLI keeps only thin, scriptable verbs. serverwatch installnow restarts an already-running service on an in-place
upgrade (enable + restart) instead ofenable --now, which only started a
stopped service.- Documentation is ctl-first throughout, with download-first install
instructions and dedicated plugin pages.
Fixed
serverwatch-ctlnow treatsSERVERWATCH_CONTROL_TOKENas the token value
(as the front-doors and web supervisor set it), not a file path, fixing an
"unexpected server hello" handshake failure forserverwatch cli/web.- Telegram command authorization is enforced against the enrolled owner chat
(security hardening). - Mobile web UI: the header no longer forces horizontal page scroll (dropped
the fixed-width heartbeat, title flexes/truncates); the active-alerts card no
longer widens the page on long unbreakable alert keys; the monitoring tab
strip scrolls within itself instead of overflowing.
Security
- Per-launch control-socket token with a constant-time compare,
0600socket
in a0700runtime directory, and checksum-manifest verification before any
plugin is exec'd. A security review was run over the web UI and control paths,
with findings triaged and tracked.
See CHANGELOG.md for the full entry. Download the three binaries for your arch into one directory and run sudo ./serverwatch install; verify against checksums.txt.
v0.4.0-beta.7 - detailed + modernized CLI, mobile tabs fix
Preview on the develop line; stable remains v0.3.2 on main. Polishes the redesigned serverwatch-ctl and fixes one more mobile web-UI overflow.
serverwatch-ctl
- Home is now a fuller dashboard. Alongside the SYSTEM (CPU/MEM/SWAP meters + live CPU sparkline, load, temp) and ALERTS panels, Home now shows network throughput, a DISKS panel (top mounts by usage, each with a coloured usage bar), and a 24h availability strip (green up / red down blocks with uptime %, total downtime, and incident count).
- Modernized Manage screens. The management menu and its sub-screens are restyled to match Home: emoji-tagged menu rows, a highlighted (accent-coloured) selected row, and coloured on/off/unavailable state badges in the channels and monitor-thresholds tables.
Web UI
- Mobile monitoring tabs (Containers/Services/Filesystems/Processes) now scroll horizontally within their own strip instead of pushing the whole page sideways; every tab stays fully readable.
Carried forward from beta.6/beta.5
The rest of the CLI redesign (styled Home, ? help overlay, breadcrumbs, --json/config/channels subcommands), the earlier mobile header + alerts-card overflow fixes, front-door token auth, and install restart-on-upgrade.
Binaries
Three binaries per arch (linux amd64/arm64/arm, darwin amd64/arm64). Download all three for your arch into one directory and run sudo ./serverwatch install. Verify against checksums.txt.
v0.4.0-beta.6 - redesigned CLI + mobile overflow fixes
Preview on the develop line; stable remains v0.3.2 on main. Adds a redesigned serverwatch-ctl and fixes mobile web-UI overflow.
serverwatch-ctl: redesigned Home + scriptable verbs
- Styled Home dashboard. The plain key/value Home is now a live dashboard: an online/offline status header with "updated Ns ago", a boxed SYSTEM panel with colour-coded CPU/MEM/SWAP meter bars, a live CPU sparkline (a rolling ~80s history), load averages and temperature, a boxed ALERTS panel listing the top firing alerts (severity dots, "(acked)", "+N more") or a "✓ no active alerts" empty state, and a glyphed inventory line (containers, units, disks, processes). Colours match the web UI's palette; no colour is emitted to a non-tty.
?help overlay. Press?on Home for a full keymap; breadcrumbs on the Web-setup and Manage screens show where you are.- New scriptable subcommands (the non-interactive counterpart to the TUI):
serverwatch-ctl status|doctor|alerts --jsonfor piping into jq etc. (--jsonworks before or after the verb).serverwatch-ctl config get <key>/config set <key> <value>reach every flat config key through the same validated setter the TUI uses;setapplies live.serverwatch-ctl channels test <name>sends a live test notification.
Web UI: mobile overflow fixes
- The mobile header no longer scrolls the page sideways: the fixed-width decorative heartbeat is dropped on phones, the title flexes and truncates, and the status pill stays on one line. This was clipping the header and the tiles beneath it.
- The Active-alerts card can no longer widen the page: panels (grid children) may shrink, long unbreakable alert keys ellipsize, and reasons wrap.
Fixes carried from beta.5
Front-door token auth (serverwatch cli/web) and serverwatch install restart-on-upgrade.
Binaries
Three binaries per arch (linux amd64/arm64/arm, darwin amd64/arm64). Download all three for your arch into one directory and run sudo ./serverwatch install. Verify against checksums.txt.
v0.4.0-beta.5 - front-door token auth + install restart fixes
Preview on the develop line; stable remains v0.3.2 on main. This is a fix release over beta.4, surfacing two bugs found deploying beta.4 to a live host.
Fixes since v0.4.0-beta.4
serverwatch cli/webfront-doors now authenticate correctly.serverwatch-ctlwas treating theSERVERWATCH_CONTROL_TOKENenv var (which the front-doors and the web supervisor set to the per-launch token VALUE) as a file path and trying to read the token string as a file, so it sent an empty token and the control-socket handshake failed with "unexpected server hello". It now reads the env var as the value, matchingserverwatch-web. (serverwatch-ctlrun directly, reading the token file, was unaffected.)serverwatch installnow restarts the service on an in-place upgrade. It usedsystemctl enable --now, which only starts a stopped service, so upgrading an already-running serverwatch left the old daemon running until a manual restart. Install now doesenable+restart, so both a fresh install and an upgrade end on the just-installed binary.
Everything from beta.4 (full-fledged serverwatch-ctl reaching every config key, one-step plugin install, the mobile web UI, and the documentation overhaul) carries forward.
Binaries
Three binaries, standard cross-compiles (linux amd64/arm64/arm, darwin amd64/arm64). Download all three for your arch into one directory and run sudo ./serverwatch install once. Verify against checksums.txt with sha256sum -c.