TrinetraSees what you can’t.

Quiet until it matters.

One small daemon per Linux server watches the box, keeps its own history and tells you on Telegram when something is wrong. When you have more than one server, the same daemon becomes a fleet master that groups alerts into incidents, routes them and escalates. No cloud, no Prometheus, no external database.

Memory
11.6 MB
CPU
~0.4% of a core
Core dependencies
Go stdlib only
Licence
FSL-1.1-ALv2
23:00:00

Nine servers, one of them the master. Nothing is wrong, so nothing is sent. Pick a failure.

9 online0 stale0 down
  • ops-mastermaster
    cpu 18%
    tag:master
  • api-01online
    cpu 44%
    tag:prod tag:api
  • api-02online
    cpu 39%
    tag:prod tag:api
  • db-01online
    cpu 31%
    tag:prod tag:db
  • web-01online
    cpu 27%
    tag:prod tag:web
  • web-02online
    cpu 24%
    tag:prod tag:web
  • cache-01online
    cpu 13%
    tag:prod
  • worker-01online
    cpu 45%
    tag:batch
  • edge-01online
    cpu 9%
    tag:edge
  1. The decision trail appears here, the same trail fleet explain prints.
Telegram0 alerts raised · 0 messages to you
  1. No messages. Nothing needs you.

A simulation of a Trinetra fleet in your browser, on the handbook’s timings: stale after 30 seconds, down after 2 minutes, a 30-second wait to group alerts, and a child delivering its own alert when the master has not confirmed it within 2 minutes. Time runs thirty times faster.

The whole box on one screen.

Containers, systemd units, filesystems, reachability, a 24-hour availability strip, CPU, memory, swap, load, temperature, network and processes, streamed live, with whatever is firing right now.

Trinetra dashboard: host strip, container and systemd counts, a 24-hour availability strip, live resource tiles and active alerts

The real web UI, trinetra-web, on a demo fleet of twelve servers. Host names, addresses and users are made up.

Rules you can read

Static thresholds, and an opt-in baseline that asks whether a reading is normal for this box. Both are plain arithmetic, so you can predict when an alert fires. No AI decides.

Set by command, not by hand

Every setting goes through the CLI or the terminal UI, which validate it and write one private config file atomically. Most changes apply without a restart.

Works when the network doesn’t

Every host alerts on its own. In a fleet, a child hands alerts to the master and delivers them itself if the master does not answer.

One message when it starts. One when it ends.

Each check is either firing or clear, and Trinetra only speaks when that changes. A disk that stays full for twenty minutes is one message, not twenty. Drag the threshold and count.

A CPU or memory alert also names the culprit, the top process and container, so it reads like cpu = 96.0 ≥ threshold 95.0 (top: ffmpeg 82%, container web 30%). Active alerts survive a restart, so a reboot does not re-send everything that was already known.

60708090100one sample a minute, for an hour
Checked on every sample23 messages
Trinetra2 messages
  1. disk:/ = 86.2 ≥ threshold 85.0
  2. disk:/ back to normal

Seven ways to reach you.

Each channel has its own severity floor, its own kinds of alert and its own quiet-hours rule, so the ops chat hears everything and email hears only criticals. Boot and recovery reports, a daily digest and a weekly rollup travel the same way.

Channels page listing Telegram, Slack and webhook channels with their severity floors and routing
ChannelWhat it needs
TelegramA bot token from @BotFather. The bot also answers /stats, history and controls.
EmailAn SMTP host, a sender and recipients
Slack, DiscordAn incoming-webhook URL
ntfyA topic, on ntfy.sh or your own server
GotifyA server and an application token
WebhookA URL, and a Go template if the receiver wants its own JSON

A dead-man switch on healthchecks.io can alert you while the box itself is off, which nothing on the box can do.

A fleet is three commands away.

Make one host the master and enroll the rest with a join code. The code pins the master’s certificate authority, so a child never trusts on first use, and from then on every child talks to the master over mutual TLS.

# on the master
sudo trinetra fleet init --address monitor.example.com
sudo systemctl restart trinetra
sudo trinetra fleet token create --tags prod --uses 3

# on each server, with the code the master printed
sudo trinetra fleet join swj1_...
sudo systemctl restart trinetra

A child keeps monitoring, storing and alerting exactly as it did alone. It also ships a copy of its history to the master through an outbox on disk, so an outage only delays the copy.

Every node at a glance.

Online, lagging, down and revoked counts, a heatmap you can switch between CPU, memory, disk and load, top-five lists and link health. Ctrl-K or ⌘-K opens any child's full dashboard from the master's copy of its data.

Fleet overview: node counts, a CPU heatmap of twelve servers, top-five CPU, memory and disk, a down-now list and the node table

Ten servers with one problem page you once.

Alerts from across the fleet are grouped into incidents. Each one has a timeline of what fired, who was told, what was held back and why. The same trail prints on the command line with trinetra fleet explain.

Incident detail: ack and silence controls, the member alerts per node, and a timeline of fired, grouped, delivered and escalated events

Routes and escalation you can test before you save.

Routes match on tag, node, rule and severity and hand an incident to a policy: the ops chat now, on-call after five minutes, everyone after fifteen. The route tester answers where a made-up alert would go.

Routes editor with ordered routes matching tags, nodes, rules and severities, and a continue toggle

Planned work pages nobody.

One-off silences by node, tag, rule or severity, and maintenance windows that recur by weekday in a named time zone. They are pushed to every child, so a child delivering on its own during an outage still honours them.

Silences page: an active silence for edge-01, the new-silence form and two recurring maintenance windows

Tune a whole tier at once.

The master pushes thresholds, quiet hours and baseline settings to every node with a tag. Each node reports what it applied, and drift or a conflict shows up against its name.

Managed config: fragments by tag and each node's applied, drift and conflict status

Rules across the whole fleet.

Alert on a tier as a whole with a small grammar that is not PromQL. The master checks every rule every 30 seconds against each node’s replica.

avg(tag:api, cpu) > 75 for 5m            # the api tier is running hot
online(tag:prod) < 8 for 2m              # lost production capacity
absent(tag:staging, 10m)                 # staging went quiet
count(tag:web, disk > 90) >= 1 for 5m    # any web node nearly full

It installs nothing it cannot verify twice.

Every release ships a manifest of exact file hashes, signed by the build pipeline and co-signed offline by a maintainer. A host checks both against keys compiled into the binary it is already running, and treats GitHub and the network as untrusted transport.

trinetra update apply restarts under a guard. If the new daemon is not healthy within 90 seconds, it goes back to the build that was. You can also check a download by hand with sha256sum and OpenSSL, without trusting Trinetra at all.

What is true about this release?
$ sudo trinetra update applyInstalled and confirmed

Staged, smoke-tested, swapped in, restarted, and confirmed healthy. The version floor moves up to it.

Small, and measured.

Heavy features are separate programs. The web UI and the terminal UI talk to the daemon over a local socket, so their dependencies never reach it, and each runs only if you install it.

Measured on Linux containers with 8 vCPUs over about 72 minutes, sampling every 10 seconds, six times the default rate. A default install is lighter still.

Core daemon11.8 MB static on amd64, 10.9 MB on arm644.3 to 4.7 MB gzipped
Memory11.6 MB RSS on its own12.4 MB as a fleet child, 14.0 MB as a master with two children
CPUAbout 0.4% of one core0.6% as a child, 1.2% as a master with two children
DiskAbout 0.3 MB of history per hostafter the first hour, with tiered retention
Web UI plugin7.7 MB RSS, about 0.07% CPUand only when you turn it on
Third-party code in the coreNonethe daemon is Go's standard library, enforced by a test

Where it fits.

Against the tools people most often run on a handful of Linux servers, from each project’s own docs as of September 2026. Where a vendor publishes no number, the table says so.

Compared onTrinetraNetdataPrometheus stackBeszelUptime Kuma
What you runOne daemon per serverAgent per server, optional parents and cloudExporters, Prometheus, Alertmanager, GrafanaAgent per server and a hubOne server, checks from outside
Memory per host11.6 MB100–200 MB empty, 250–350 MB typicalNot documentedNot documentedNo agent
Central server downEvery host still alertsAgents still alertNothing firesNothing firesNothing fires
Incidents and escalationBuilt inIn Netdata CloudWith Alertmanager configPer-metric alertsPer-monitor alerts

Pick Netdata for per-second metrics and anomaly detection, Prometheus for custom metrics and PromQL, Uptime Kuma for checking sites from outside, and Beszel if you need an MIT licence. The full comparison covers Zabbix and Datadog too, with sources.

Install it.

Any Linux with systemd: Ubuntu, Debian, Raspberry Pi OS, Fedora, RHEL. Pick the architecture of the server, not of your laptop. The current release is Trinetra 0.5.0.

Servers, VMs and NUCs

mkdir -p ~/trinetra-download && cd ~/trinetra-download && arch=linux-amd64
for b in trinetra trinetra-ctl trinetra-web; do
  curl -fsSL -o "$b" "https://github.com/InfoDiveLabs/trinetra/releases/latest/download/$b-$arch"
done
for f in manifest.json manifest.ci.sig manifest.maint.sig; do
  curl -fsSL -o "$f" "https://github.com/InfoDiveLabs/trinetra/releases/latest/download/$f"
done
chmod +x trinetra trinetra-ctl trinetra-web

Then two commands.

sudo ./trinetra install --require-signed
sudo trinetra cli

install checks both signatures and every hash, refuses on any mismatch, then installs the daemon and whichever plugins sit beside it and starts the systemd service. cli walks you through the Telegram bot token and turning on the web UI.

The one required setting is the bot token. Send the bot /start with the PIN it prints, and it answers only you. Then send /stats.

The docs cover the web UI, channels, fleets, updates and upgrading from serverwatch.

On a desk, a tablet or a phone.

Light and dark themes, an icon rail on a tablet and a bottom tab bar on a phone. Sign in with a passkey: Touch ID, Windows Hello or a security key. There are no passwords.

The dashboard in the light theme
The fleet page on a tablet with the icon rail
The fleet page on a phone with the bottom tab bar

What is not done yet.

Written down so nobody has to find out.

  • Linux with systemd only. v0.4.1 was the last release with macOS builds. There is no Windows build and no official container image.
  • Channel checks in the web UI. Saving a channel there does not test it end to end yet. The terminal UI does, and so does trinetra channel test.
  • Per-interface throughput alerts. Network throughput is collected and charted, but nothing alerts on it yet.
  • Fleet in the terminal and in Telegram. The terminal UI has no fleet screens yet, and the bot has no /fleet or /incidents commands. Ack and Silence 1h buttons on incident messages do work.
  • Telegram buttons trust the chat. Anyone in the enrolled chat can tap Ack, as anyone in it can already send commands.
  • No metrics export. Nothing speaks Prometheus or remote-write, and none is being built right now.

One eye on every server.

One light is on. Trinetra already told you which one.