Las herramientas de monitorización le avisan cuando un servidor o un sitio web deja de funcionar, pero las primeras señales de alerta se esconden en los logs: un disco que se llena un poco más cada día, un error que se repite cientos de veces, una oleada de intentos de fuerza bruta por SSH, un proceso que consume CPU sin que nadie lo note. Pocas personas leen esos logs cada mañana. Esta guía recopila los datos clave una vez al día, deja que un modelo de lenguaje local en Ollama los convierta en un informe breve y fácil de leer con comprobaciones sugeridas, y lo envía a Telegram. Como el modelo se ejecuta en su propio servidor, los logs nunca salen de él.
Necesita Ollama con un modelo pequeño, configurado como se explica en ejecutar un LLM local con Ollama, además de jq y curl. Cree un bot con @BotFather en Telegram, envíele cualquier mensaje y luego obtenga el ID de su chat:
apt install -y jq curl
ollama pull qwen2.5:7b
# Send any message to your bot first, then:
curl -s "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates" | jq '.result[].message.chat.id'
mkdir -p /opt/aireport
cat > /opt/aireport/report.sh <<'EOF2'
#!/bin/bash
# Daily AI server report: collect facts, summarise them with Ollama, send to Telegram
MODEL="qwen2.5:7b"
LANGUAGE="Simplified Chinese" # language of the report
TG_TOKEN="123456789:replace-with-your-bot-token"
TG_CHAT="123456789"
FACTS=/opt/aireport/facts.txt
{
echo "Host: $(hostname) Uptime: $(uptime -p)"
echo "Load average 1/5/15 min: $(cut -d' ' -f1-3 /proc/loadavg) CPU cores: $(nproc)"
echo; echo "## Memory"; free -h
echo; echo "## Disk usage"; df -h -x tmpfs -x devtmpfs -x overlay
echo; echo "## Failed systemd units"; systemctl --failed --no-legend
echo; echo "## Most frequent error messages in the last 24 hours"
journalctl --since "24 hours ago" -p err --no-pager -o cat | sort | uniq -c | sort -rn | head -20
echo; echo "## Failed SSH password logins in the last 24 hours (count, then top source IPs)"
journalctl --since "24 hours ago" --no-pager -o cat | grep -c "Failed password"
journalctl --since "24 hours ago" --no-pager -o cat | grep -oP "Failed password .* from \K[0-9a-fA-F.:]+" | sort | uniq -c | sort -rn | head -5
if [ -f /var/log/nginx/access.log ]; then
echo; echo "## Nginx HTTP status codes since the last log rotation"
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -8
echo; echo "## URLs with the most 5xx errors"
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -5
fi
echo; echo "## Top processes by CPU"
ps -eo user,pid,%cpu,%mem,etime,comm --sort=-%cpu | head -8
} > "$FACTS" 2>&1
PROMPT="You are an experienced Linux operations engineer. Below are today's facts from a server.
Write a short daily report in $LANGUAGE for the server owner:
1. First line: overall status, one of OK / ATTENTION / PROBLEM.
2. Then at most 5 bullet points about anything unusual, each with the likely cause and one command to check it.
3. If everything looks normal, say so in one sentence.
Only use the facts below. Do not invent numbers.
$(head -c 12000 "$FACTS")"
REPORT=$(jq -n --arg m "$MODEL" --arg p "$PROMPT" \
'{model: $m, prompt: $p, stream: false, options: {temperature: 0.2, num_ctx: 8192}}' \
| curl -s --max-time 900 http://127.0.0.1:11434/api/generate -d @- | jq -r '.response // empty')
[ -z "$REPORT" ] && REPORT="AI summary failed. Raw facts:
$(head -c 3000 "$FACTS")"
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
--data-urlencode "chat_id=${TG_CHAT}" \
--data-urlencode "text=[$(hostname)] daily report
${REPORT:0:3800}" > /dev/null
EOF2
chmod 700 /opt/aireport/report.sh
Sustituya el token del bot y el ID del chat. Solo root puede leer el script, porque contiene el token. num_ctx da al modelo contexto suficiente para toda la hoja de datos, y el informe se recorta para ajustarse al límite de longitud de los mensajes de Telegram. Si el modelo no responde, recibirá igualmente los datos sin procesar.
/opt/aireport/report.sh
cat /opt/aireport/facts.txt # the data the model saw
La primera ejecución tarda más porque el modelo tiene que cargarse. Compare varias veces el informe con facts.txt para valorar la fiabilidad de los resúmenes en sus servidores, y ajuste el prompt si reacciona de más o de menos.
echo '0 8 * * * root /opt/aireport/report.sh' > /etc/cron.d/aireport
timedatectl | grep "Time zone" # cron uses the server's time zone
Añada más secciones dentro de las llaves del script; todo lo que impriman pasa a formar parte de los datos. Algunos ejemplos útiles:
echo; echo "## Fail2ban"; fail2ban-client status sshd | grep -E "Currently banned|Total banned"
echo; echo "## Stopped Docker containers"; docker ps -a --filter status=exited --format "{{.Names}}: {{.Status}}"
echo; echo "## Certificates"; for c in /etc/letsencrypt/live/*/cert.pem; do echo "$c $(openssl x509 -enddate -noout -in "$c")"; done
echo; echo "## Last backup file"; ls -lt /backup | head -3
Guías relacionadas: Fail2ban para SSH y Nginx, certificados SSL gratuitos y su renovación y, para bloques de IP, monitorizar automáticamente un bloque de IP alquilado.
No hace falta ejecutar Ollama en todos los servidores. Ejecute solo la parte de recopilación de datos en cada servidor, copie facts.txt al servidor que tiene Ollama (por ejemplo, con scp desde cron y una clave SSH) y genere allí todos los informes. Si prefiere llamar directamente a un Ollama central, hágalo a través de una red privada o una VPN, nunca abriendo el puerto 11434 a Internet.
En CPU el modelo escribe despacio, lo cual no es un problema para una tarea diaria. Para obtener informes más rápidos, use un modelo más pequeño como qwen2.5:3b o acorte la hoja de datos eliminando las secciones que no necesite.
Técnicamente sí, pero los logs contienen direcciones IP, nombres de usuario, URL y, a veces, datos de clientes. Enviarlos a un tercero tiene implicaciones de privacidad y debe hacerse conforme a las condiciones del proveedor y en sus regiones admitidas. Un modelo local evita este problema.
Ejecute el comando sugerido y revise los datos sin procesar. Si ve procesos desconocidos que consumen mucha CPU o inicios de sesión inesperados, siga la guía cómo comprobar si un servidor Linux ha sido hackeado.
¿Sigue sin resolverlo después de seguir estos pasos? Abra un ticket de soporte y el equipo técnico de IMIDC, disponible 24/7, le ayudará. Incluya la IP del servidor, la versión del sistema operativo, el contenido de facts.txt y el informe que recibió para que podamos localizar el problema más rápido.