Automatización
Diun y alertas en Telegram: entérate de las imágenes nuevas sin actualizar a ciegas
7 min de lectura
Puntos clave
- Diun avisa de imágenes nuevas pero no actualiza nada: tú decides cuándo.
- Revisa cada día a una hora fija todos los contenedores, salvo los que excluyas.
- Diun no avisa si una etiqueta fijada desaparece del registro: revísalas de vez en cuando.
- Un único bot de Telegram sirve para Diun, CrowdSec y Uptime Kuma.
- Token y chat id en ficheros .env con permisos 600, nunca en el repo.
Antes usaba Watchtower: vigilaba mis contenedores, los actualizaba solo y me avisaba después. Es cómodo, pero choca con una idea que para mí es básica: saber en todo momento qué versión corre cada servicio y poder volver atrás.
Ahora hago lo contrario: fijo las versiones en cada docker-compose.yml y actualizo a mano, con un commit. Para no quedarme atrás, uso Diun, que solo me avisa de que hay algo nuevo. Los avisos llegan a Telegram, por el mismo bot que usan el resto de mis servicios.
Qué vas a montar
- Diun (Docker Image Update Notifier) en Docker, revisando tus contenedores una vez al día.
- Un bot de Telegram propio y el id de tu chat.
- Los avisos de Diun, CrowdSec y Uptime Kuma en ese mismo bot.
- Una comprobación periódica de que las etiquetas fijadas siguen existiendo.
Requisitos
- Docker y Docker Compose.
- Una cuenta de Telegram.
- Opcional: CrowdSec y Uptime Kuma, de la serie “Mi NAS paso a paso”. Uptime Kuma lo monté en Uptime Kuma: vigila tus servicios y enseña su estado en vivo en tu CV.
Paso 1: crear el bot de Telegram
- En Telegram, abre una conversación con @BotFather (el bot oficial para crear bots).
- Envía
/newbot. - Elige un nombre visible y un nombre de usuario que termine en
bot. - BotFather te devuelve un token. Es la contraseña del bot: guárdalo y no lo compartas.
Ahora necesitas el id de tu chat, que es a quién enviará el bot los mensajes. Abre una conversación con tu bot, envíale cualquier mensaje y ejecuta:
# Pega el token solo en esta variable temporal
read -rs TG_TOKEN
curl -s "https://api.telegram.org/bot${TG_TOKEN}/getUpdates"
read -rs pide el valor sin mostrarlo en pantalla ni guardarlo en el historial. En la respuesta JSON, busca "chat":{"id":...}: ese número es tu chat id.
Paso 2: los secretos, en un .env
Guarda el token y el chat id en un fichero compartido para tus propios scripts, fuera de cualquier repo:
# /volume1/docker/.notify.env — nunca en Git
TG_TOKEN=
TG_CHAT=
chmod 600 /volume1/docker/.notify.env
Y comprueba que funciona con un mensaje de prueba:
# Carga las variables sin escribir el token en el comando
set -a
. /volume1/docker/.notify.env
set +a
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
--data-urlencode "chat_id=${TG_CHAT}" \
--data-urlencode "text=Prueba desde el NAS: los avisos funcionan"
Si la respuesta empieza por {"ok":true, el mensaje ya está en tu móvil.
Paso 3: Diun en Docker
services:
diun:
image: crazymax/diun:4 # etiqueta de versión mayor
container_name: diun
restart: unless-stopped
env_file: .env # token y chat id de Telegram
volumes:
- ./data:/data # base de datos de imágenes vistas
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
TZ: Europe/Madrid
LOG_LEVEL: info
DIUN_WATCH_SCHEDULE: "0 8 * * *" # cada día a las 08:00
DIUN_WATCH_FIRSTCHECKNOTIF: "false" # no avisa en el primer escaneo
DIUN_PROVIDERS_DOCKER: "true"
DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT: "true" # vigila todos los contenedores
security_opt:
- no-new-privileges:true
mem_limit: 64m
labels:
- diun.enable=false # no se vigila a sí mismo
Y su .env, con permisos 600:
DIUN_NOTIF_TELEGRAM_TOKEN=
DIUN_NOTIF_TELEGRAM_CHATIDS=
Cada ajuste tiene su motivo:
0 8 * * *. Una vez al día, a una hora en la que lo voy a leer. Más a menudo solo genera ruido y peticiones al registro.WATCHBYDEFAULT: true. Vigila todos los contenedores sin tener que etiquetarlos uno a uno. Para excluir alguno, ponle la etiquetadiun.enable=false, como hace Diun consigo mismo.FIRSTCHECKNOTIF: false. En el primer escaneo lo ve todo por primera vez. Sin esto, recibirías un aviso por cada contenedor.- El socket en solo lectura (
:ro) y 64 MB. Diun solo consulta; no necesita más.
docker compose up -d
docker exec diun diun notif test # envía una notificación de prueba
Qué vigila exactamente
Por defecto, Diun comprueba si la imagen detrás de tu etiqueta ha cambiado en el registro. Por eso encaja bien con etiquetas de versión mayor, como crazymax/diun:4 o louislam/uptime-kuma:1: cuando sale una versión nueva dentro de esa rama, la etiqueta apunta a otra imagen y Diun avisa.
Si fijas una versión exacta, como :1.23.4, esa etiqueta no cambia nunca y Diun no dirá nada de la 1.23.5. Para eso tiene una opción: la etiqueta diun.watch_repo=true en el contenedor le hace revisar las etiquetas del repositorio, y diun.include_tags las filtra con una expresión regular.
El caso real: la etiqueta que desapareció
Fijar versiones es buena práctica, y aun así me dio un susto. Tenía Uptime Kuma fijado en una etiqueta antigua (:1.23). Un día tuve que recrear el contenedor y no pude: esa etiqueta ya no existía en el registro, así que Docker no pudo descargar la imagen.
Diun no me avisó, y es normal: Diun avisa de versiones nuevas, no de etiquetas que desaparecen. Por eso ahora compruebo de vez en cuando que las imágenes que uso siguen existiendo:
#!/usr/bin/env bash
# Comprueba que cada imagen en uso sigue disponible en su registro
set -uo pipefail
docker ps --format '{{.Image}}' | sort -u | while read -r image; do
if docker manifest inspect "$image" > /dev/null 2>&1; then
echo "OK $image"
else
echo "FALTA $image"
fi
done
Las imágenes que construyes tú en local también saldrán como FALTA, porque no están en ningún registro: ignóralas. Otra forma sencilla es ejecutar docker compose pull en la carpeta de cada stack: si una etiqueta ya no existe, falla antes de que tengas que recrear nada.
Paso 4: un bot para todos
Uso el mismo bot para todo lo que tiene que avisarme. Los mensajes llegan al mismo chat, mezclados, y para mí es una ventaja: todo lo importante está en un sitio.
CrowdSec
CrowdSec envía sus avisos con su plugin HTTP. Este es un ejemplo del fichero de notificación (en mi caso, notifications/http.yaml):
type: http
name: telegram
log_level: info
# Agrupa avisos: sin esto, un escaneo con 50 IPs serían 50 mensajes
group_wait: 30s
group_threshold: 10
# El texto va en UNA línea con \n escapados: un salto de línea real rompe el JSON
format: |
{"chat_id": "TU_CHAT_ID", "text": "CrowdSec:\n{{range .}}{{range .Decisions}}{{.Value}} bloqueada por {{.Scenario}} durante {{.Duration}}\n{{end}}{{end}}"}
url: https://api.telegram.org/botTU_TOKEN/sendMessage
method: POST
headers:
Content-Type: application/json
Sustituye TU_TOKEN y TU_CHAT_ID por tus valores, activa la notificación telegram en el perfil de CrowdSec y protege el fichero con chmod 600: aquí el token está en claro.
Dos cosas que aprendí aquí: la agrupación (group_wait y group_threshold) evita que un escaneo te llene el móvil de mensajes, y el text debe ir en una sola línea con \n escapados. Con un salto de línea real dentro de la cadena, el JSON deja de ser válido y Telegram responde con un error 400.
Uptime Kuma
En Uptime Kuma, en los ajustes de notificaciones, añade una de tipo Telegram con el mismo token y chat id. Márcala para que se aplique por defecto a los monitores nuevos y usa el botón de prueba. Es lo que me habría avisado del contenedor que estuvo semanas parado sin que nadie se enterara.
Problemas frecuentes
| Síntoma | Causa probable | Solución |
|---|---|---|
getUpdates devuelve una lista vacía |
No has escrito al bot | Envíale un mensaje y repite |
| Telegram responde 401 | Token incorrecto | Cópialo de nuevo desde BotFather |
| Telegram responde 400 | JSON inválido o chat id erróneo | Texto en una línea con \n; revisa el id |
| Una avalancha de avisos al arrancar Diun | Primer escaneo con avisos | DIUN_WATCH_FIRSTCHECKNOTIF: "false" |
| Diun no avisa de una versión nueva | Etiqueta exacta que no cambia | Etiqueta de versión mayor o diun.watch_repo=true |
| No se puede recrear un contenedor | La etiqueta fijada ya no existe | Revisa las etiquetas con el script de arriba |
Conclusión
Diun me da lo mejor de los dos mundos: sé cuándo hay algo nuevo, pero ninguna actualización ocurre sin que yo lo decida. La lección de la etiqueta perdida es sencilla: fijar versiones no es “configurar y olvidar”; hay que revisarlas.
Con un único bot de Telegram, todos los avisos del homelab llegan a un solo sitio. Y si quieres ver el estado de tus servicios además de recibir avisos, en el capítulo de Uptime Kuma de la serie “Mi NAS paso a paso” explico cómo publicarlo incluso en tu CV.
Preguntas frecuentes
¿Por qué Diun y no Watchtower?
Watchtower actualiza los contenedores solo. Yo fijo versiones y actualizo a mano con un commit, así sé qué cambió y puedo volver atrás. Diun solo me avisa.
¿Es seguro montar el socket de Docker en Diun?
El socket da mucho poder, así que lo monto en solo lectura y limito el contenedor. Diun solo necesita consultar qué contenedores e imágenes hay.
¿Puedo usar un bot distinto para cada servicio?
Sí. Yo uso uno para todo y los avisos llegan mezclados al mismo chat. Si quieres separarlos, crea otro bot con BotFather y cambia el token en ese servicio.
Fuentes
Proyecto relacionado
Infraestructura Pesoz
Homelab self-hosted en producción 24/7: un NAS Synology con ~30 servicios en Docker tras Caddy + CrowdSec y un portátil con GPU como servidor de IA y observabilidad en k3s. VPN WireGuard, GitOps con Forgejo y estado en vivo con Uptime Kuma.




