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
| Command | Shows |
|---|---|
/status | The glance card: sync status, height and lag vs external RPC, epoch/round, peers, 24h own blocks, throughput, raptorcast p99, txpool, service states, identity |
| 🔄 Refresh | Re-scrape and redraw the card in place |
| 📡 Live | Recent own block events from the ledger tail |
| 🏦 Staking | Stake, 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:
| Source | Provides |
|---|---|
| Node metrics endpoint | Height, commits, peers, proposals, statesync, consensus events, raptorcast p99, txpool |
monad-ledger-tail journal | Your own proposed / finalized / timeout blocks, filtered by your secp key |
monad-status | Service states, epoch/round, statesync, block lag vs external RPC |
| Local RPC, staking precompile | Validator 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
monprobeuser that is not in themonadgroup — 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 themonaduser 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 is0600, and the token is redacted from all log output.
monprobe is MIT licensed. Issues and pull requests are welcome on GitHub.