instalar uptime kuma con docker
Aprende a desplegar uptime kuma en docker para monitorear sitios, puertos y dns. Configura alertas por telegram y publica páginas de estado desde un vps.
Lo que vas a construir
Un único contenedor pequeño que monitorea tus otros servidores y sitios web desde el exterior. Te notificará mediante email, Telegram, Discord o un webhook en el momento en que uno deje de responder. Uptime Kuma es un proceso de Node respaldado por un archivo SQLite, por lo que funciona sin problemas con 256-512 MB de RAM. Proporciona un dashboard en tiempo real, gráficos de historial y una página de estado pública. La instalación consiste en un archivo Compose de diez líneas; lo importante es dónde lo ejecutas y si tus alertas funcionan en una prueba, porque un monitor cuya capacidad de notificación no ha sido probada es peor que no tener ninguno: genera una falsa sensación de seguridad mientras no recibes nada.
Ejecute el monitor en un lugar que la interrupción no pueda alcanzar
Esta decisión determina el éxito de todo el sistema, por lo que es lo primero que debe considerar. No ejecute Uptime Kuma en la misma máquina que los servicios que supervisa. Si el monitor reside en el servidor que supervisa, el evento que intenta detectar (como la caída del servidor o la falta de memoria) también detendrá el monitor. Esto impide recibir alertas, ya que el silencio de un monitor inactivo es indistinguible de un estado de "todo funciona correctamente". Existe otro riesgo cuando el servidor sigue activo: un monitor configurado para localhost comparte la CPU con la carga de trabajo. Un pico de carga puede causar un timeout en la comprobación y marcar el objetivo como down (falsa alarma), mientras los usuarios reales siguen operando sin problemas.
Por lo tanto, ejecute Uptime Kuma en un VPS distinto al que supervisa, idealmente con un proveedor o región diferentes. El monitor debe alcanzar sus servicios de la misma forma que sus usuarios: a través de internet público y mediante hostname. Una instancia económica es suficiente, y un solo VPS de monitoreo puede supervisar todos sus servidores. Para detectar si el propio Kuma ha fallado, configure un push heartbeat mediante un cron en otro equipo.
Requisitos previos y dimensionamiento
- Un VPS con Ubuntu 24.04 recién instalado que incluya Docker Engine y el plugin Compose v2. Instálelos desde el repositorio apt oficial de Docker, no desde el paquete de la distro
docker.io, ya que este se encuentra desactualizado. - 256 MB de RAM son suficientes para ejecutar unos pocos monitores; de 512 MB a 1 GB es ideal para decenas de monitores más el reverse proxy, manteniendo el uso de CPU cerca de cero entre cada comprobación.
- Un dominio y un registro DNS
A(por ejemplo,status.example.comapuntando al VPS), solo si requiere TLS y una página de estado pública. Una instancia privada puede omitir el DNS y utilizar una VPN o un túnel SSH. - Conexión de red de salida hacia los destinos de las alertas: SMTP para su proveedor de correo, o HTTPS para Telegram y Discord.
El archivo Compose
Guarde esto en /srv/uptime-kuma/compose.yaml.
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: unless-stopped
ports:
- "127.0.0.1:3001:3001"
volumes:
- kuma-data:/app/data
volumes:
kuma-data:Inicie el contenedor y observe el primer arranque:
sudo mkdir -p /srv/uptime-kuma
# save the file above as /srv/uptime-kuma/compose.yaml, then:
cd /srv/uptime-kuma && sudo docker compose up -d
sudo docker compose logs -f uptime-kumaUn inicio correcto registra Listening on 3001 y deja de emitir mensajes. Tres elementos en ese archivo son deliberados.
127.0.0.1:3001:3001, no 3001:3001. Docker publica los puertos mediante reglas DNAT que se evalúan antes de que ufw detecte el paquete. Por tanto, un 3001:3001 simple expone su panel de control a internet, independientemente de su firewall. Vincularlo al loopback mantiene la instancia privada y solo expone el proxy inverso; una instancia privada puede omitir el proxy y acceder a 3001 mediante una VPN WireGuard auto-hospedada en su lugar.
Un volumen con nombre en /app/data. Todo lo que Uptime Kuma almacena —la base de datos SQLite, sus monitores, la configuración de notificaciones y los logotipos de la página de estado— reside allí. Si lo pierde, comenzará con una pantalla de administración vacía; es el único elemento que debe realizar copia de seguridad.
La imagen está fijada a una etiqueta de versión principal, :2. Esa es la línea estable actual; verifique en Docker Hub la versión principal más reciente antes de copiarla. Nunca utilice etiquetas dinámicas como latest, ya que el proyecto las considera obsoletas. Un salto de versión principal en esta imagen implica una migración de base de datos unidireccional; debe ejecutarse de forma deliberada y no por error durante un pull rutinario.
Una advertencia: /app/data debe estar en un sistema de archivos con bloqueos de archivos POSIX. Un volumen de Docker local es adecuado; en NFS la base de datos SQLite se corrompe y obtendrá SQLITE_BUSY y database disk image is malformed, por lo que nunca utilice un recurso compartido de red.
Primera ejecución: crear la cuenta de administrador
Acceda a la instancia a través de su proxy en https://status.example.com, o mediante un túnel SSH: ejecute ssh -L 3001:127.0.0.1:3001 user@your-vps y abra http://localhost:3001. La primera página es un formulario de configuración para el nombre de usuario y la contraseña del administrador; no existe un inicio de sesión predeterminado. Elija una contraseña segura: este panel tiene acceso a las direcciones internas y tokens de todo lo que monitorea. ¿La olvida después? Restablézcala desde el host, no desde el navegador:
sudo docker compose exec uptime-kuma npm run reset-passwordPrimero añada sus canales de notificación y pruébelos
Configure las alertas antes de añadir los monitores para poder adjuntar un canal mientras crea cada uno. Vaya a Settings then Notifications then Setup Notification, y use el botón Test de cada canal para confirmar la recepción del mensaje; una notificación no probada es la segunda causa más común de fallos silenciosos en la configuración.
Email (SMTP). Complete el host, port, encryption, username, password, un From y un To. Las dos combinaciones funcionales son 465 con "Secure" en TLS/SSL, o 587 con STARTTLS. Para Gmail y la mayoría de proveedores con autenticación de dos factores, debe generar un app password; una contraseña de cuenta normal devuelve Error: Invalid login: 535-5.7.8 Username and Password not accepted.
Telegram. Envíe un mensaje a @BotFather, envíe /newbot y copie el bot token. Para su chat ID, envíe un mensaje al nuevo bot una vez, abra https://api.telegram.org/bot<token>/getUpdates y lea chat.id en el JSON. Un bot al que nunca se ha enviado un mensaje primero tiene un getUpdates vacío y no tiene destino de envío.
Discord. En el canal, abra Edit Channel then Integrations then Webhooks then New Webhook, copie la URL y péguela como una notificación de Discord.
Generic webhook. Para cualquier otro servicio, como un incoming webhook de Slack, un endpoint personalizado o un hook de domótica, el tipo Webhook realiza un POST de un payload JSON a la URL que usted proporcione. La integración Apprise incluida cubre la mayoría de los noventa servicios restantes de la lista.
Añadir monitores, uno a la vez
Haga clic en Add New Monitor, elija un tipo y configure el Friendly Name, el Check Interval (60 segundos es un valor razonable), los Retries (fallos consecutivos antes de marcar como "down"; use 2 o 3 para evitar alertas por un solo paquete perdido) y las notificaciones a ejecutar. Los tipos que utilizará son:
- HTTP(s). Una URL completa. El estado "up" significa un código de estado aceptado (200-299 por defecto; amplíe el rango en Accepted Status Codes si
301o401es normal en su caso). Es la herramienta principal para sitios web y APIs. - HTTP(s) - Keyword. La misma petición, pero el estado "up" también requiere que una cadena de texto esté presente en el cuerpo (o que la opción Invert esté desactivada). Esto detecta si el sitio devuelve
200 OKmientras muestra el mensaje "Error establishing a database connection", algo que una comprobación HTTP simple marcaría como saludable. - TCP Port. Una conexión TCP básica a un host y puerto, para servicios que no son HTTP: SSH en el 22, Postgres en el 5432, un servidor SMTP en el 25 o un servidor de juegos.
- Ping. Eco ICMP: comprobación de latencia y alcanzabilidad de bajo coste. Sin embargo, muchas redes y firewalls de la nube descartan ICMP; un monitor de ping en rojo puede significar "host caído" o "el proveedor bloquea el ping"; confirme esto con un monitor TCP.
- DNS. Resuelve un registro (A, AAAA, MX, TXT, etc.) mediante un resolver definido por usted. Puede validar la respuesta para detectar fallos en el registrador o en el servicio DNS de forma temprana.
- Push. El monitor de tipo "push", que se explica a continuación.
Monitoreo de un cron job con un monitor de tipo push (heartbeat)
Todos los monitores anteriores consultan su servicio desde el exterior. Un monitor de tipo push funciona de forma inversa: Uptime Kuma espera y su tarea lo llama para confirmar que se ejecutó. Es la única forma fiable de supervisar un backup o un cron: un chequeo HTTP solo sabe si una URL responde, pero solo la tarea sabe si se completó correctamente.
Cree un monitor de tipo Push. Uptime Kuma generará una URL única como:
https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=OK&ping=Configure el Heartbeat Interval con la frecuencia de ejecución de la tarea, más un margen de tiempo adicional. Luego, añada una línea al final del script para que se ejecute solo si la tarea tiene éxito:
#!/usr/bin/env bash
set -euo pipefail
# ... your backup or job runs here; set -e aborts on any failure ...
curl -fsS --retry 3 "https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=backup+ok&ping="Si la tarea falla, set -e se interrumpe antes de ejecutar el curl; si el servidor está apagado, la tarea tampoco se ejecutará. En ambos casos, el heartbeat se detiene y, una vez transcurrido el intervalo más los reintentos, Uptime Kuma marcará el monitor como down y enviará una alerta. Trate ese push token como una clave secreta: cualquier persona que lo tenga puede simular un estado saludable.
Crear una página de estado pública
Una página de estado es la vista para el cliente: muestra qué servicios están activos y su historial reciente sin exponer su panel de control. Vaya a Status Pages then New Status Page, asigne un nombre y un slug (la ruta pública, como /status/main), arrastre los monitores deseados a grupos como "Websites" y "APIs", añada un logo y una descripción corta, y haga clic en Save. También puede vincular la página a su propio dominio para que status.example.com la sirva directamente.
Dos advertencias: añada solo los monitores que esté dispuesto a hacer públicos, ya que una página de estado revela la existencia de un servicio y su estado de actividad; y el dashboard permanece protegido tras su login, mientras que la página de estado es intencionadamente pública y no requiere autenticación.
Utilice un reverse proxy con TLS y configure los websockets
Para una instancia pública, coloque un reverse proxy delante del contenedor vinculado al loopback para obtener TLS y un hostname. El detalle que causa errores: la interfaz de Uptime Kuma es una aplicación Socket.IO en tiempo real, por lo que el proxy debe realizar el upgrade de la conexión WebSocket. Si no se configura, la página cargará pero nunca se conectará; el dashboard mostrará "Connecting...", los heartbeats en vivo no se actualizarán y la consola del navegador mostrará WebSocket connection to 'wss://.../socket.io/...' failed.
Instale nginx y certbot, luego escriba el vhost que actúe como proxy hacia el puerto loopback. Utilice el puerto 80 por ahora y deje que certbot añada TLS después; los detalles sobre el desafío, el temporizador de renovación y sus fallos de funcionamiento se cubren en issuing Let's Encrypt certificates with certbot and nginx.
sudo apt install -y nginx certbot python3-certbot-nginxGuarde esto como /etc/nginx/sites-available/status.example.com; las dos líneas de WebSocket son las críticas:
server {
listen 80;
server_name status.example.com;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
}
}Habilite el sitio, pruebe la configuración y deje que certbot reescriba el bloque para escuchar en el puerto 443, inserte el certificado y añada una redirección de HTTP a HTTPS:
sudo ln -s /etc/nginx/sites-available/status.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d status.example.comEl par Upgrade y Connection "upgrade" es lo fundamental, y proxy_read_timeout 3600s evita que nginx cierre la conexión del socket de larga duración; certbot copia ambos en el bloque 443 que genera. Si ya ejecuta varios contenedores detrás de un único proxy, routing them through Traefik with automatic TLS realiza lo mismo mediante etiquetas de contenedor y reenvía los upgrades de WebSocket por defecto.
No aplique basic-auth a todo el vhost, ya que esto bloqueará la página de estado pública y el endpoint /api/push. Mantenga el login integrado de Uptime Kuma, añada fail2ban watching for repeated failed logins si tiene acceso desde internet y, si el dashboard no necesita ser público, elimine el proxy y acceda mediante una VPN.
Monitoreo de expiración de certificados de forma correcta
Un monitor HTTP(s) también puede avisar antes de que un certificado TLS expire: marque Certificate Expiry Notification y Uptime Kuma enviará alertas con un número determinado de días de antelación. Dos errores causan lecturas incorrectas. Monitoree por hostname, no por IP; de lo contrario, una solicitud sin SNI obtendrá el certificado por defecto del servidor y verá Hostname/IP does not match certificate's altnames. Además, no marque Ignore TLS/SSL Error en un monitor del cual desee recibir avisos de expiración: esa opción es para hosts internos con certificados autofirmados (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT), pero impide que Uptime Kuma verifique el certificado, incluyendo su fecha de expiración.
Backups: es un directorio
Como todo reside en /app/data, un backup es una copia de ese volumen realizada con el contenedor detenido para asegurar la consistencia del archivo SQLite:
cd /srv/uptime-kuma
sudo docker compose stop
sudo docker run --rm \
-v uptime-kuma_kuma-data:/data \
-v /var/backups/kuma:/backup \
alpine tar czf /backup/kuma-$(date -u +%Y%m%dT%H%M%SZ).tgz -C /data .
sudo docker compose startPrimero confirme el nombre real del volumen con docker volume ls | grep kuma, ya que Compose añade el prefijo del directorio del proyecto. Luego copie el archivo tar fuera del servidor, porque un backup en el mismo VPS es solo una copia, no un respaldo. La restauración es el proceso inverso: detenga el stack, extraiga el contenido en un volumen /app/data vacío y arránquelo.
Actualizaciones
Las actualizaciones consisten en la descarga de una imagen:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dEl nuevo contenedor ejecuta cualquier migración de base de datos al iniciar; monitoree docker compose logs -f. Realice el respaldo mencionado anteriormente antes de la descarga y manténgase dentro de una etiqueta mayor: el paso de :1 a :2 es una migración unidireccional, por lo que debe realizar un respaldo primero y revisar las notas de la versión.
Modos de fallo y los mensajes que verá
Falso estado "down" en un monitor apuntando a localhost. El monitor cambia a rojo con timeout of 48000ms exceeded o connect ETIMEDOUT, pero el servicio responde desde su laptop. Si el monitor apunta al mismo host donde se ejecuta Uptime Kuma, un pico de CPU o memoria causó el fallo, no el objetivo. Mueva el monitor a un VPS separado y apunte al hostname público.
connect ECONNREFUSED 127.0.0.1:443 (o cualquier puerto). No hay nada escuchando en ese puerto: el servicio está caído o monitoreó localhost desde dentro del contenedor, donde 127.0.0.1 es el contenedor y no su servidor. Monitoree el hostname público, no el loopback.
Invalid login: 535-5.7.8 Username and Password not accepted en una prueba de email. Las credenciales SMTP son incorrectas, o el proveedor requiere una contraseña de aplicación y recibió la contraseña de su cuenta. Genere una contraseña de aplicación y úsela.
connect ETIMEDOUT o queryA ETIMEDOUT <host> en una prueba de email. Puerto incorrecto o el proveedor bloquea el tráfico SMTP saliente. Confirme que 465 o 587 coincida con la configuración Secure/STARTTLS, y realice una prueba desde el host con nc -vz smtp.example.com 587. Muchos proveedores bloquean el tráfico 25 saliente y algunos bloquean los puertos de envío hasta que se solicita.
self signed certificate o unable to verify the first certificate en una prueba de email. Su servidor SMTP presenta un certificado que Node no reconoce como confiable; corrija el certificado del servidor de correo en lugar de ignorar el error.
El Dashboard se queda en "Connecting...", la consola muestra WebSocket connection ... failed. El proxy inverso no está realizando el upgrade de WebSocket. Agregue los headers Upgrade y Connection "upgrade" en nginx, o use un proxy que los reenvíe por defecto como Traefik o Caddy. El HTML carga porque es una petición HTTP GET normal; solo el socket en vivo requiere el upgrade.
El monitor de expiración de certificados no avisa, o avisa incorrectamente. La opción Ignore TLS/SSL Error está marcada, lo que desactiva la verificación de certificados, o el monitor apunta a una IP y lee el certificado incorrecto por falta de SNI, mostrando Hostname/IP does not match certificate's altnames. Desmarque la opción de ignorar y monitoree por hostname.
SQLITE_BUSY o database disk image is malformed en los logs. El volumen /app/data está en un filesystem sin bloqueo de archivos adecuado, usualmente NFS; muévalo a un volumen local de Docker y restaure desde un backup.
FAQ
¿Dónde debería ejecutar mi monitor de uptime?
En un servidor distinto a los que supervisa. Lo ideal es usar otro proveedor o región, conectando mediante hostname a través de internet público, tal como lo hacen sus usuarios. Si el monitor comparte equipo con los objetivos, una caída del servidor también detendrá el monitor. Además, un host sobrecargado puede reportar falsos positivos de caída en servicios que funcionan correctamente. Un VPS pequeño y separado evita ambos problemas.
¿Cómo recibo alertas en Telegram o por email?
Añada el canal en Settings then Notifications y asígnelo a cada monitor. Para Telegram, cree un bot con @BotFather y obtenga el chat.id desde https://api.telegram.org/bot<token>/getUpdates. Para email, use 465 para SSL o 587 para STARTTLS con una contraseña de aplicación si su proveedor usa autenticación de dos factores. Presione Test y confirme que el mensaje llega antes de confiar en el sistema.
¿Puede Uptime Kuma monitorear un cron job o un script de backup?
Sí, mediante el monitor tipo Push: Uptime Kuma le proporciona una URL y usted la curl al finalizar el script para que la alerta se active solo si tiene éxito. Si el proceso falla o el servidor está caído, el heartbeat nunca llegará y recibirá una alerta tras pasar el intervalo configurado. Es la única forma fiable de saber si una tarea programada se ejecutó realmente, ya que una comprobación externa no puede inspeccionar el interior del proceso.
Uptime Kuma vs Zabbix, ¿cuál debería ejecutar?
Uptime Kuma responde a "¿está activo desde el exterior y me ha avisado?" en diez minutos y con casi ningún recurso, además de incluir una página de estado. No recopila métricas profundas como tendencias de CPU, memoria o disco, ni umbrales para flotas completas. Para eso, un servidor de monitoreo Zabbix completo es la herramienta más pesada basada en agentes; muchos usuarios ejecutan ambos. ¿Aún no decide qué ejecutar? nuestra selección de qué auto-alojar en 2026 le ayuda a contextualizar el monitoreo.