Monad

Monitoring

Monitoring your Monad validator with monprobe, EmberStake's on-node Telegram bot

monprobe

monprobe is a lightweight Telegram bot we built for Monad validators. Send /status from your phone and get a one-screen answer about your node.

It is deliberately not a remote alerting service. It runs on the node itself, reads only that node, and nothing leaves the machine except the Telegram messages to you. Think of it as a pocket glance: check from your phone, and if something looks wrong, go to your laptop and dig in. It does include a minimal watchdog, but that watchdog lives on the node too — if the server dies, the bot dies with it. If you need external, always-on alerting, monprobe complements that rather than replacing it.

  • On-node and private — no dashboard, no third-party service seeing your validator
  • Lightweight — one static Go binary, one systemd unit, zero listening ports
  • Read-only — the bot can report, never act

What it shows

CommandShows
/statusThe glance card: sync status, height and lag vs external RPC, epoch/round, peers, 24h own blocks, throughput, raptorcast p99, txpool, service states, identity
🔄 RefreshRe-scrape and redraw the card in place
📡 LiveRecent own block events from the ledger tail
🏦 StakingStake, active-set standing, reliability over 24h/7d/30d, payouts, registration status

The watchdog messages you only when something is actually wrong — height frozen past a threshold, metrics endpoint unreachable, a core service down, or a burst of missed leader slots — once per condition, with a recovery message when it clears and a cooldown so it cannot spam you. Alerts carry the validator name from the config, so one Telegram chat can serve several nodes.

Where the data comes from

Everything is read locally from your own node. There is no external dependency:

SourceProvides
Node metrics endpointHeight, commits, peers, proposals, statesync, consensus events, raptorcast p99, txpool
monad-ledger-tail journalYour own proposed / finalized / timeout blocks, filtered by your secp key
monad-statusService states, epoch/round, statesync, block lag vs external RPC
Local RPC, staking precompileValidator ID, stake, commission, active-set membership, unclaimed rewards

Notably the staking figures are read from the staking precompile through your own node's RPC, never an external endpoint.

Requirements

A binary-mode Monad node — systemd services, not Docker — with monad-status at /usr/local/bin/monad-status and the monad-ledger-tail service running.

Install

The installer downloads the prebuilt static binary from the latest release (sha256 verified), checks the node preconditions, then asks for your Telegram bot token and chat ID, validator name and secp public key:

curl -fsSL https://raw.githubusercontent.com/EmberStake/monprobe/main/scripts/install-remote.sh -o monprobe-install.sh

sudo bash monprobe-install.sh

Download the script to a file first as shown — the interactive prompts do not work when piped straight into a shell. For unattended installs (Ansible and similar), pass the same values as environment variables instead:

sudo env MONPROBE_TG_TOKEN="123:ABC" MONPROBE_TG_CHAT_ID=123456789 \
  MONPROBE_VALIDATOR_NAME="my-validator" \
  MONPROBE_SECP_KEY="03..." \
  bash monprobe-install.sh

You will need a bot token from @BotFather and your Telegram chat ID. Once the service is running, send /status — if the card shows the Identity section, everything is wired up correctly.

systemctl status monprobe

journalctl -u monprobe -f

Building from source and the full configuration reference are covered in the repository README.

Security model

monprobe is built to open zero holes in your validator:

  • No inbound ports. It uses Telegram long polling, which is outbound-only. A port scan of your validator looks identical before and after installing it.
  • No shell, no injection surface. Messages are matched against a fixed dispatch table; user input never becomes part of a command, path or URL.
  • Least privilege. Runs as a dedicated monprobe user that is not in the monad group — it cannot read your validator keys even if compromised.
  • One narrow sudo rule, permitting exactly one argument-less command (monad-status, which prints public identifiers only). The installer verifies that binary cannot be modified by the monad user and refuses to install otherwise.
  • Allowlist. Only the chat IDs you list get any response; unknown senders get silence.
  • Sandboxed systemd unit with a read-only filesystem view, private /tmp, no device access and a minimal capability set. The config file holding your bot token is 0600, and the token is redacted from all log output.

monprobe is MIT licensed. Issues and pull requests are welcome on GitHub.