Skip to content

Releases: InfoDiveLabs/trinetra

v0.5.0 - fleet mode, signed self-update

Choose a tag to compare

@github-actions github-actions released this 29 Sep 19:26

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 fleet commands: init, join, leave, disable,
    status, nodes, node revoke|rename|tag, and token create|list|delete.
    See the command reference.
  • Config keys fleet.listen (default :9443), fleet.outbox_max_mb
    (default 512) and fleet.node_down_after (default 2m). The role and
    identity keys are managed by trinetra fleet and refused by config set.
  • Control socket: requests take an optional node to read a remote node's
    replica through the same methods, plus new Fleet.* methods for fleet
    management. Both are backward compatible: requests without node behave 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_after or 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 and continue fan-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. New trinetra fleet subcommands: incidents, incident, ack, explain, silence add|list|expire, maintenance add|list|delete, route test, alerting show|apply, rules, managed list|set|delete|status, and node depends.
    New config keys fleet.fallback_after (default 2m) and
    fleet.link_down_warn_after (default 10m), 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). /fleet gains 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-signed runs the same signature check for
    the initial install. New config keys update.channel (default stable),
    update.source (default github), update.github_token, and
    update.check_interval (default 24h); 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."): module github.com/InfoDiveLabs/trinetra, binaries trinetra,
    trinetra-ctl, trinetra-web, paths /etc/trinetra, /var/lib/trinetra,
    /run/trinetra, and the trinetra.service unit. The web UI, TUI, and
    notifications carry the new Trinetra visual identity. The GitHub repo moves
    to InfoDiveLabs/trinetra (the old Suraj-Tiwari/server-monitor URLs
    redirect).
    • Upgrade: download trinetra and 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
      disables serverwatch.service, moves /etc/serverwatch →
      /etc/trinetra and /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/serverwatch with a compat symlink to
      trinetra; /usr/bin/serverwatch is deliberately left pointing at it
      rather than redirected or removed, so sudo serverwatch ... still
      resolves via secure_path on 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-path adopts a state volume
      you moved yourself, --force proceeds past a serverwatch.service
      systemd could not confirm was stopped or a serverwatch daemon still
      running outside it (found through its pid file). An old plugin with no
      trinetra-ctl/trinetra-web counterpart next to trinetra is named in
      a WARNING: line of the summary. Until install has run, trinetra daemon and 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-serverwatch marker 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.json key names; the control.sock/token file names inside the
      runtime dir; the /usr/local/bin/serverwatch → trinetra compat symlink
      and the /usr/bin/serverwatch link that keeps pointing at it (both
      removed in the next release); the
      SERVERWATCH_CONTROL_SOCKET/TOKEN environment fallback (also removed in
      the next release); and the literal "serverwatch-control" control-socket
      ha...
Read more

channels

Choose a tag to compare

@github-actions github-actions released this 29 Sep 19:27

Signed channel pointers.

v0.4.1 - server identity, security hardening, reliability

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 20 Aug 14:35

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.name across web, ctl, and alert titles; host inventory (CPU/RAM/disks/OS/uptime) on a new web Host page, serverwatch-ctl host, and core.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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 08 Aug 14:22

Five tracker issues, all with core / web / ctl parity.

Added

  • Versions in the panel (#107). Build-time version stamp per binary (git-derived, dev fallback for plain go 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 version prints 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, and serverwatch-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 doctor warns 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 install no 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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 08 Aug 09:53

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, snap squashfs/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 (validated docker logs --tail over the socket), also serverwatch-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 /config Identity panel sets server.name and toggles the collect.public_ip opt-in.
  • Downtime list paginated on the history page (8 plus "Show all").

Server identity (#99)

  • Configurable server.name (name, then hostname, then serverwatch); web brand, ctl header/config, [name]-prefixed alert titles (#101)
  • Host inventory over core.API.HostInfo(): web Host page plus serverwatch-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 with textContent (#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

v0.4.1-beta.1 Pre-release
Pre-release

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 02 Aug 18:20

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 -race on 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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 02 Aug 07:17

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 internal core.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-web out 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
    when web.enabled is set. The default serverwatch binary 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-ctl subcommands. status, doctor, and
    alerts gain --json output; 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.Subscribe runs
    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-web subscribing to push live dashboard updates.
  • Front-door install and safe-exec. serverwatch install records each
    plugin's checksum in a root-only manifest; the serverwatch cli and
    serverwatch web front-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-prod builds stripped,
    trimmed binaries (-s -w -trimpath) for the stable line, alongside the
    unstripped make release used for beta/dev builds.

Changed

  • The web UI no longer builds with -tags web inside the daemon; it is a
    separate supervised process. Guided setup (web UI, Telegram onboarding) is
    owned by serverwatch-ctl; the core CLI keeps only thin, scriptable verbs.
  • serverwatch install now restarts an already-running service on an in-place
    upgrade (enable + restart) instead of enable --now, which only started a
    stopped service.
  • Documentation is ctl-first throughout, with download-first install
    instructions and dedicated plugin pages.

Fixed

  • serverwatch-ctl now treats SERVERWATCH_CONTROL_TOKEN as the token value
    (as the front-doors and web supervisor set it), not a file path, fixing an
    "unexpected server hello" handshake failure for serverwatch 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, 0600 socket
    in a 0700 runtime 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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 02 Aug 07:03

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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 02 Aug 07:28

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 --json for piping into jq etc. (--json works 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; set applies 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

Choose a tag to compare

@Suraj-Tiwari Suraj-Tiwari released this 02 Aug 06:07

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/web front-doors now authenticate correctly. serverwatch-ctl was treating the SERVERWATCH_CONTROL_TOKEN env 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, matching serverwatch-web. (serverwatch-ctl run directly, reading the token file, was unaffected.)
  • serverwatch install now restarts the service on an in-place upgrade. It used systemctl 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 does enable + 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.