Alertas via Telegram: notificações do servidor

    Um bot do Telegram é a forma mais rápida e gratuita de receber alertas críticos do servidor — downtime, erros 500, disco cheio, deploy concluído — direto no celular. Sem configuração de SMTP, sem planos pagos, sem apps extras: só a API HTTP do Telegram.

    Criar bot e obter token

    Configurar o bot no Telegram e obter o chat ID:

    bash
    # 1. Criar bot:
    #    → Abra o Telegram → pesquise @BotFather
    #    → /newbot → escolha nome → escolha username (termina em _bot)
    #    → Anote o TOKEN: 1234567890:AABBCCddeeffgghhiijj...
    
    # 2. Obter seu Chat ID:
    #    → Mande qualquer mensagem para o seu bot
    #    → Abra no browser:
    #    https://api.telegram.org/bot<TOKEN>/getUpdates
    #    → Procure: "chat":{"id": 123456789}
    #    → Esse é seu CHAT_ID
    
    # 3. Testar envio:
    TOKEN="SEU_TOKEN"
    CHAT_ID="SEU_CHAT_ID"
    
    curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
      -H "Content-Type: application/json" \
      -d '{
        "chat_id": "'"$CHAT_ID"'",
        "text": "✅ Bot configurado com sucesso!",
        "parse_mode": "HTML"
      }'
    
    # Para grupos: adicione o bot ao grupo e use o ID do grupo (negativo)
    # Para canais: adicione como admin e use @nome_do_canal como chat_id

    Função de envio no Node.js

    Módulo reutilizável para enviar alertas da aplicação:

    typescript
    // lib/telegram.ts
    const TELEGRAM_TOKEN = process.env.TELEGRAM_BOT_TOKEN!
    const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID!
    
    interface AlertOptions {
      emoji?: string
      silent?: boolean  // notificação sem som
    }
    
    export async function enviarAlerta(mensagem: string, opts: AlertOptions = {}) {
      const { emoji = '', silent = false } = opts
    
      const texto = emoji ? `${emoji} ${mensagem}` : mensagem
    
      const response = await fetch(
        `https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            chat_id: TELEGRAM_CHAT_ID,
            text: texto,
            parse_mode: 'HTML',
            disable_notification: silent,
          }),
        }
      )
    
      if (!response.ok) {
        console.error('Falha ao enviar alerta Telegram:', await response.text())
      }
    }
    
    // Alertas tipados para contextos comuns:
    export const alertas = {
      erro: (msg: string) => enviarAlerta(`❌ <b>ERRO</b>\n${msg}`),
      aviso: (msg: string) => enviarAlerta(`⚠️ <b>AVISO</b>\n${msg}`),
      info: (msg: string) => enviarAlerta(`ℹ️ ${msg}`, { silent: true }),
      deploy: (versao: string) => enviarAlerta(`🚀 <b>Deploy concluído</b>\nVersão: ${versao}`, { silent: true }),
      downtime: (servico: string) => enviarAlerta(`🔴 <b>DOWNTIME</b>\n${servico} não está respondendo`),
    }

    Monitoramento de disco e memória com cron

    Script shell para alertas automáticos de recursos do servidor:

    bash
    #!/bin/bash
    # /opt/scripts/alertas-vps.sh
    
    TOKEN="${TELEGRAM_BOT_TOKEN}"
    CHAT_ID="${TELEGRAM_CHAT_ID}"
    HOST=$(hostname)
    
    alerta() {
        curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
          -d "chat_id=$CHAT_ID" \
          --data-urlencode "text=$1" \
          -d "parse_mode=HTML" > /dev/null
    }
    
    # ── Disco ────────────────────────────────────────────────
    USO_DISCO=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
    if [ "$USO_DISCO" -gt 85 ]; then
        alerta "⚠️ <b>Disco crítico em $HOST</b>
    Uso: ${USO_DISCO}% do disco /
    $(df -h / | awk 'NR==2')"
    fi
    
    # ── Memória ──────────────────────────────────────────────
    MEM_LIVRE=$(free -m | awk '/^Mem:/ {print $7}')
    if [ "$MEM_LIVRE" -lt 200 ]; then
        alerta "⚠️ <b>Memória baixa em $HOST</b>
    Disponível: ${MEM_LIVRE} MB
    $(free -h | head -2)"
    fi
    
    # ── Load average ─────────────────────────────────────────
    LOAD=$(cat /proc/loadavg | awk '{print $1}')
    CPUS=$(nproc)
    LOAD_INT=$(echo "$LOAD * 10" | bc | cut -d. -f1)
    LIMIT=$((CPUS * 15))  # alerta se load > 1.5x CPUs
    if [ "$LOAD_INT" -gt "$LIMIT" ]; then
        alerta "🔴 <b>CPU sobrecarregada em $HOST</b>
    Load average: $LOAD ($(nproc) CPUs)
    $(top -bn1 | head -8)"
    fi
    
    # Crontab (verificar a cada 5 min):
    # */5 * * * * root /opt/scripts/alertas-vps.sh

    Integrar com Prometheus Alertmanager

    Receber alertas do Prometheus via Telegram:

    yaml
    # alertmanager.yml — receiver para Telegram:
    global:
      resolve_timeout: 5m
    
    route:
      receiver: 'telegram'
      group_wait: 10s
      group_interval: 5m
      repeat_interval: 4h
    
    receivers:
      - name: 'telegram'
        webhook_configs:
          - url: 'http://localhost:3001/alertmanager-webhook'
            send_resolved: true
    
    # Node.js — handler do webhook do Alertmanager:
    app.post('/alertmanager-webhook', express.json(), async (req, res) => {
      const { alerts, status } = req.body
    
      for (const alert of alerts) {
        const emoji = status === 'resolved' ? '✅' : '🔴'
        const estado = status === 'resolved' ? 'Resolvido' : 'Disparado'
        const severity = alert.labels.severity ?? 'unknown'
    
        const msg = `${emoji} <b>${estado}: ${alert.labels.alertname}</b>
    Severidade: ${severity}
    Instância: ${alert.labels.instance ?? 'N/A'}
    ${alert.annotations.summary ?? ''}
    ${alert.annotations.description ?? ''}`
    
        await enviarAlerta(msg)
      }
    
      res.sendStatus(200)
    })

    Formatação rica com HTML e Markdown

    Mensagens de alerta bem formatadas no Telegram:

    typescript
    // O Telegram suporta HTML e MarkdownV2 nas mensagens.
    // parse_mode: 'HTML' é mais simples:
    
    // Formatação HTML disponível:
    // <b>negrito</b>
    // <i>itálico</i>
    // <code>código inline</code>
    // <pre>bloco de código</pre>
    // <a href="url">link</a>
    
    // Template de alerta de erro de aplicação:
    export function alertaErroAplicacao(params: {
      titulo: string
      erro: string
      rota?: string
      usuario?: string
      ambiente: string
    }) {
      const { titulo, erro, rota, usuario, ambiente } = params
      return `🚨 <b>${titulo}</b>
    
    <b>Ambiente:</b> ${ambiente}
    <b>Rota:</b> ${rota ?? 'N/A'}
    <b>Usuário:</b> ${usuario ?? 'anônimo'}
    
    <b>Erro:</b>
    <pre>${erro.slice(0, 300)}</pre>
    
    ⏰ ${new Date().toLocaleString('pt-BR', { timeZone: 'America/Sao_Paulo' })}`
    }
    
    // Usar no tratamento de erros globais:
    process.on('uncaughtException', async (err) => {
      await enviarAlerta(alertaErroAplicacao({
        titulo: 'Exceção não tratada',
        erro: err.stack ?? err.message,
        ambiente: process.env.NODE_ENV ?? 'production',
      }))
      process.exit(1)
    })

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes