Skip to content
RunStack
AutomationTools· Updated 16 Oct 2026

tg-exec — any command's result in Telegram

A wrapper for cron jobs, backups, deploys and CI: exit code, duration and output arrive in Telegram. Proxy support, own Bot API endpoint for closed networks, encrypted token.

UbuntuUbuntuDebianDebianCentOSCentOSAlmaLinuxAlmaLinuxRocky LinuxRocky LinuxDockerDocker
Ubuntu 20.04+ · Debian 11+ · RHEL / Alma / Rocky 8+ · Alpine 3.x · macOS 12+
20

Run a backup, an upgrade or a deploy — and learn how it ended without logging into the server. tg-exec runs the command, shows its output in the terminal as usual and sends a short report to Telegram when it finishes.

❌ Failed · exit 2 · backup-db01
  pg_dump app | gzip > /backup/app.sql.gz
🕒 2026-10-16 03:00:00 → 03:02:03 UTC · 2m 3s
💬 Output:
  pg_dump: error: connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed

What it does

  • The exit code is passed through. The wrapper does not break cron, systemd or CI: tg-exec -- backup.sh returns exactly what backup.sh returned. A signal gives 128+N, a timeout gives 124.
  • The job comes first. If the token is missing or Telegram is unreachable, the command still runs and the problem goes to stderr.
  • Clean output. The message carries the output tail without ANSI colours or redrawn progress bars. If it does not fit, the full log arrives as a file (up to 45 MB).
  • Arguments stay intact. tg-exec -- rsync -a "/src dir/" host:/dst is executed directly, without re-parsing by a shell. A single quoted string goes through bash -c, so pipes and && work.
  • Errors only, if you like. --on-failure reports failures only, --silent delivers successes without sound, --timeout 2h stops a stuck job.
  • Groups, channels, forum topics. The --setup wizard finds the chat id from recent messages to the bot.

Closed networks

tg-exec talks to nothing but the Telegram Bot API and does not need RunStack to work.

  • Proxies: http://, https://, socks5://, socks5h:// with username and password.
  • Your own API endpoint — a self-hosted telegram-bot-api or an nginx gateway, plus a custom CA for an internal certificate.
  • One static binary with no dependencies: Linux amd64 / arm64 / armv7 / 386 and macOS. deb, rpm and apk packages.

A protected token

To be honest: if a program reads a token without a password — and cron leaves no other option — whoever gets that account's rights can read it too. So tg-exec closes what can actually be closed:

  • the config with the token is created with mode 0600, and a more open one triggers a warning;
  • sudo tg-exec --seal encrypts the token with systemd-creds using the host key and TPM2 when available. A copied disk or backup is useless without this server;
  • TOKEN_CMD works like aws-cli credential_process: the token comes from Vault, pass or any other secrets manager;
  • systemd LoadCredentialEncrypted= exposes the token to one service only.

Getting started

  1. Create a bot with @BotFather.
  2. Install tg-exec — package and source links are available after sign-in.
  3. Run sudo tg-exec --setup: token check → pick a chat → test message.
tg-exec -- apt-get -y upgrade
tg-exec --on-failure -n nightly-backup -t 3h -- /usr/local/bin/backup.sh
tg-exec "pg_dump app | gzip > /backup/app.sql.gz"

All settings are in man tg-exec and tg-exec --help. Current settings and a delivery test: tg-exec --check.

Materials are available after sign-in and email verification.