Rénich's Blog

Bots de Telegram: La consola de ChatOps definitiva para Sysadmins

Hero image for Bots de Telegram: La consola de ChatOps definitiva para Sysadmins

06 de julio de 2026 • 5 min de lectura

Hoy te vengo a hablar de una herramienta que, para muchos, nomás sirve para mandar memes o jugar trivias en chats grupales. Pero la neta, si eres sysadmin o te late el desmadre del self-hosting y la administración de servidores, la API de Bots de Telegram es una mina de oro. Es, sin temor a equivocarme, la consola de ChatOps más barata y potente que te puedes echar a la bolsa.

Dejate de andar batallando con pasarelas de SMS de paga o configurando servidores de correo SMTP que de todos modos van a terminar en la carpeta de spam. Con un bot de Telegram tienes un canal de comunicación directo, encriptado y gratis para controlar tus fierros desde cualquier lugar.

Aquí te cuento las características clave y ejemplos bien prácticos para que los corras tú mismo:

Alertas automáticas en caso de fallos

Para notificaciones rápidas, no necesitas montar ninguna infraestructura compleja. Puedes crear un script de notificación para systemd que te avise de volada si algún servicio importante se cae.

Primero, creas el script que hace el envío:

# /usr/local/bin/systemd-telegram-notify.bash
#!/usr/bin/bash
set -euo pipefail
IFS=$'\n\t'

readonly BotToken="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
readonly ChatId="987654321"

main() {
    local -r service_name="${1:-}"
    if [[ -z "$service_name" ]]; then
        printf "Usage: %s <service_name>\n" "${0##*/}" >&2
        return 1
    fi

    local message
    message=$(printf "❌ *Servicio Caído*\n*Host:* %s\n*Servicio:* \`%s\`\n*Hora:* %s" \
        "$(hostname)" \
        "$service_name" \
        "$(date '+%Y-%m-%d %H:%M:%S')")

    curl -s -X POST "https://api.telegram.org/bot${BotToken}/sendMessage" \
         -d "chat_id=${ChatId}" \
         -d "parse_mode=MarkdownV2" \
         -d "text=${message}"
}

main "$@"

Luego, creas un archivo de unidad de servicio genérico para systemd:

# /etc/systemd/system/telegram-notify@.service
[Unit]
Description=Enviar alerta de Telegram al fallar %I

[Service]
Type=oneshot
ExecStart=/usr/local/bin/systemd-telegram-notify.bash %i

Ahora, en cualquier servicio que quieras vigilar (como nginx.service), nomás agregas la directiva OnFailure=telegram-notify@%n.service en la sección [Unit]. Si el servicio truena, ¡te llega el pitazo al celular de inmediato!

Comandos de control y autenticación segura

Puedes programar tu bot para que escuche comandos y te regrese el estado del sistema. Lo mejor es que la API de Telegram hace la autenticación por ti. Cada mensaje entrante contiene el ID numérico verificado del usuario.

Aquí tienes un micro-daemon en Crystal, sin dependencias externas, que escucha comandos de diagnóstico de forma segura:

# /usr/local/bin/telegram-bot.cr
require "http/server"
require "json"
require "process"

ADMIN_ID = 987654321_i64
BOT_TOKEN = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"

server = HTTP::Server.new do |context|
  if context.request.method == "POST" && context.request.path == "/webhook"
    if body = context.request.body
      payload = JSON.parse(body.gets_to_end)
      msg = payload["message"]?
      sender_id = msg.try(&.["from"]?.try(&.["id"]?.try(&.as_i64?)))
      text = msg.try(&.["text"]?.try(&.as_s?)) || ""

      if sender_id == ADMIN_ID && text.starts_with?("/status")
        # Ejecuta un comando rápido de diagnóstico
        stdout = IO::Memory.new
        Process.run("df", args: ["-h", "/"], output: stdout)
        disk_res = stdout.to_s

        reply = "Estado de discos:\n<pre>#{disk_res}</pre>"
        send_reply(msg.not_nil!["chat"]["id"].as_i64, reply)
      end
    end
  end

  context.response.content_type = "application/json"
  context.response.status = HTTP::Status::OK
  context.response.print({status: "ok"}.to_json)
end

def send_reply(chat_id : Int64, text : String)
  client = HTTP::Client.new(URI.parse("https://api.telegram.org"))
  payload = {
    chat_id: chat_id,
    text: text,
    parse_mode: "HTML"
  }.to_json

  client.post(
    "/bot#{BOT_TOKEN}/sendMessage",
    headers: HTTP::Headers{"Content-Type" => "application/json"},
    body: payload
  )
end

address = server.bind_tcp "0.0.0.0", 8443
puts "Escuchando en http://#{address}"
server.listen

Local Bot API Server: Control local sin límites

Esta característica es una joya para sysadmins. Si no quieres que tu tráfico de red salga a los servidores en la nube de Telegram, puedes correr tu propio Local Bot API Server.

Aquí tienes un archivo de servicio de systemd para tener tu pasarela local corriendo como servicio del sistema:

# /etc/systemd/system/telegram-bot-api.service
[Unit]
Description=Telegram Bot API Local Server
After=network.target

[Service]
Type=simple
User=telegram
ExecStart=/usr/local/bin/telegram-bot-api --local --api-id=tu_api_id --api-hash=tu_api_hash --dir=/var/lib/telegram-bot-api --working-dir=/var/lib/telegram-bot-api/temp
Restart=always

[Install]
WantedBy=multi-user.target

Una vez activado, nomás apuntas tus peticiones de curl o Crystal a http://localhost:8081/bot<token>/ y listo. Ya puedes subir respaldos de hasta 2GB directamente usando la ruta local (ej. file:///var/backups/dump.sql).

Mensajería enriquecida para reportes detallados

Con el motor de Rich Messages (Bot API 10.1), ya no estás limitado a bloques de texto plano feos. Puedes mandar reportes detallados usando plantillas HTML avanzadas que se renderizan de forma nativa en la app de Telegram.

Aquí tienes un ejemplo de cómo estructurar y mandar un reporte que contiene una tabla de estados y un bloque colapsable para logs de error:

# /usr/local/bin/send-report.cr
require "http/client"
require "json"

BOT_TOKEN = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
CHAT_ID = "987654321"

# Plantilla HTML que entiende el motor Rich HTML de Telegram
rich_html = <<-HTML
<h1>Reporte del Servidor srv01</h1>
<hr/>
<p>Estado de los servicios críticos de la infraestructura:</p>
<table bordered striped>
  <tr><th>Servicio</th><th>Estado</th></tr>
  <tr><td>Nginx Webserver</td><td>🟢 Activo</td></tr>
  <tr><td>MariaDB Cluster</td><td>🟢 Activo</td></tr>
  <tr><td>Podman Daemon</td><td>🔴 Inactivo</td></tr>
</table>
<br/>
<details>
  <summary>Ver logs de error de Nginx</summary>
  <pre>2026/07/06 15:30:12 [error] 1234#0: *5 open() "/var/www/html/favicon.ico" failed</pre>
</details>
HTML

payload = {
  chat_id: CHAT_ID,
  rich_message: {
    html: rich_html
  }
}

response = HTTP::Client.post(
  "https://api.telegram.org/bot#{BOT_TOKEN}/sendRichMessage",
  headers: HTTP::Headers{"Content-Type" => "application/json"},
  body: payload.to_json
)

puts "Respuesta: #{response.status_code} - #{response.body}"

Tip

Usa el método sendRichMessageDraft para streamear salidas de terminal largas o procesos lentos en tiempo real con la etiqueta animada <tg-thinking>. ¡Parece magia!

Conclusión

A final de cuentas, los bots de Telegram dejaron de ser solo una herramienta recreativa para convertirse en una interfaz de control de sistemas sumamente flexible. La neta, integrarlos en tus scripts de administración te ahorra un montón de desveladas y te da el control de tu infraestructura en la palma de tu mano.

¿Y tú, ya usas Telegram para monitorear tus servidores o sigues dependiendo del correo?