Go Uptime: monitorización self-hosted derivada de Gatus

Mascote LinuxPro apontando uma falha no painel de status do Go Uptime num NOC, com o cachorro caramelo cyborg sentado ao lado

O Gatus es estupendo para monitorizar como código, pero se deja por fuera dos cosas que muchos equipos piden: registrar un monitor desde la web sin editar el YAML, y publicar una página de estado abierta mientras el panel sigue protegido. El Go Uptime nació para cubrir esas carencias. Es un proyecto derivado de Gatus, en un único binario Go, que mantiene la configuración en YAML y añade administración web, páginas de estado públicas, push compatible con Uptime Kuma, MySQL/MariaDB, pantalla de inicio de sesión y copia de seguridad. En esta guía verás qué cambia respecto a Gatus, cómo levantar Go Uptime con Docker o systemd y cómo configurar cada nueva funcionalidad.

De dónde viene Go Uptime

O Go Uptime comenzó en 2026 como fork de Gatus, de TwiN, a partir de un commit del 8 de septiembre de 2026. Desde la v6.0.0 sigue su propio camino: el servidor HTTP y la línea de comandos fueron reescritos. Hasta la v6.3.0 el proyecto se publicaba como jniltinho/gatus. En la v7.0.0, lanzada el 21 de septiembre de 2026,获得了 el nombre actual y la imagen jniltinho/go-uptime.

La licencia sigue siendo la misma que la del original, Apache 2.0. El archivo NOTICE registra el origen y la modificación de los archivos heredados. En la práctica, lo que importa para quien ya usa Gatus: un archivo de configuración de Gatus funciona sin modificaciones. Las condiciones, los endpoints, los grupos y los proveedores de alerta son los mismos; las funciones nuevas entran como bloques opcionales.

Dashboard do Go Uptime no tema escuro, com barras das últimas checagens e tempo médio de resposta por endpoint

Qué tiene Go Uptime además de Gatus

Todo lo que hace Gatus sigue ahí: comprobaciones HTTP, ICMP, TCP, DNS y otras, condiciones sobre estado, tiempo de respuesta, cuerpo y certificado, ventanas de mantenimiento, suites y más de 40 proveedores de alerta. Encima de eso, el proyecto añade:

  • Administración por web en /admin: crear, editar, desactivar y eliminar endpoints sin reiniciar el servicio. En Gatus, los endpoints solo existen en el archivo de configuración (TwiN/gatus#1345).
  • Páginas de estado públicas en /status/<slug>, abiertas sin inicio de sesión, con el panel protegido. En Gatus, esa petición se cerró como not planned (TwiN/gatus#1311).
  • Push compatible con Uptime Kuma: scripts y cron jobs reportan su propio estado en /api/push/<token>, con las mismas URL y respuestas que Kuma.
  • MySQL y MariaDB como almacenamiento, además de SQLite y PostgreSQL. En Gatus, MySQL no es compatible.
  • Pantalla de inicio de sesión con logout y sesiones en la base de datos, en lugar de la ventana de autenticación del navegador; curl -u sigue funcionando.
  • Copia de seguridad y restauración de lo que se ha registrado a través de la web, opcionalmente cifrado.
  • Gráfico de tiempo de respuesta por endpoint, en los periodos Recent, 3h, 6h, 24h y 1w, con promedio, mínimo y máximo.
  • Línea de comandos: config validate, password hash, version e healthcheck.
  • Tres temas (oscuro, claro y bio) y la fuente Inter servida por el propio binario, sin llamar a servicios externos.

Si quieres una interfaz para todo y no te importa Node.js, el Uptime Kuma sigue siendo una buena elección. Go Uptime se queda en el camino intermedio: YAML versionado en Git para lo que es estable, web para lo que cambia cada semana.

Levántalo con Docker en un minuto

La imagen está en Docker Hub, para amd64 e arm64. No existe tag latest, a propósito: fija la versión que ejecutas. Para una primera vistazo, sin historial persistente:

mkdir -p go-uptime/config && cd go-uptime
curl -sL -o config/config.yaml \
  https://raw.githubusercontent.com/jniltinho/go-uptime/main/config.yaml
docker run -d --name go-uptime -p 127.0.0.1:8080:8080 \
  -v "$PWD/config:/config" jniltinho/go-uptime:v7.0.0

Abre http://127.0.0.1:8080. El archivo de ejemplo ya trae endpoints y las páginas /status/services e /status/infrastructure. En pocos segundos, docker ps muestra el contenedor como healthy: la imagen no tiene shell, y el HEALTHCHECK usa el propio subcomando go-uptime healthcheck.

Producción con Docker Compose, SQLite e inicio de sesión

Para mantener el historial y conectar la administración, se necesitan tres bloques: un almacenamiento SQL, un login y admin.enabled. Comience generando el hash de la contraseña del administrador:

printf 'troque-esta-senha' | docker run --rm -i jniltinho/go-uptime:v7.0.0 password hash

El comando imprime el hash bcrypt en base64 esperado en password-bcrypt-base64. Ejecutado en un terminal sin el printf, pide la contraseña dos veces sin eco. Cree entonces config/config.yaml:

storage:
  type: sqlite
  path: /data/data.db

security:
  basic:
    username: admin
    password-bcrypt-base64: "COLE-AQUI-O-HASH"

admin:
  enabled: true

endpoints:
  - name: linuxpro
    group: sites
    url: "https://www.linuxpro.com.br"
    interval: 1m
    conditions:
      - "[STATUS] == 200"
      - "[RESPONSE_TIME] < 1000"
      - "[CERTIFICATE_EXPIRATION] > 168h"

  - name: dns-google
    group: infra
    url: "8.8.8.8"
    interval: 1m
    dns:
      query-name: "linuxpro.com.br"
      query-type: "A"
    conditions:
      - "[DNS_RCODE] == NOERROR"

Y el compose.yaml, con el puerto publicado solo en 127.0.0.1 para quedar detrás de un proxy inverso:

services:
  go-uptime:
    image: jniltinho/go-uptime:v7.0.0
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - ./config:/config:ro
      - go-uptime-data:/data

volumes:
  go-uptime-data:

Antes de levantarlo, valide la configuración. El config validate carga el archivo exactamente como lo haría el servidor, pero no abre la base de datos ni hace peticiones, y sale con código 1 si algo está mal. Es el comando adecuado para incluir en un pipeline antes del despliegue:

docker run --rm -v "$PWD/config:/config:ro" jniltinho/go-uptime:v7.0.0 config validate &&
docker compose up -d
curl -s http://127.0.0.1:8080/health

La salida esperada es algo como:

The configuration is valid: 2 endpoints, 0 external endpoints, 0 suites
{"status":"UP"}

Con security.basic activo, el panel y la API pasan a exigir inicio de sesión. /login abre una pantalla propia, la sesión queda en la base de datos (solo se guarda el hash SHA-256 del token) y la cookie es HttpOnly e SameSite=Strict. Los scripts siguen usando curl -u admin:senha. Los cambios en el archivo no requieren reinicio: Go Uptime recarga la configuración por sí mismo en hasta 30 segundos.

Los ejemplos del repositorio se ejecutan con la administración activada, usuario admin y contraseña go-uptime. Esa contraseña es pública: los ejemplos solo publican el puerto en 127.0.0.1, y debes cambiarla antes de poner un proxy delante.

Administración por web

Con el inicio de sesión configurado, /admin enumera los endpoints del YAML (solo lectura, marcados como YAML) y los registrados por la web (marcados como Web, con editar, pausar y eliminar). Los endpoints de la web se guardan en la tabla managed_endpoints de la base de datos y entran en vigor sin reinicio. El formulario tiene modo visual y modo YAML, con botón de prueba antes de guardar para endpoints activos.

Tela de administração de endpoints do Go Uptime, com endpoints vindos do YAML e cadastrados pela web

Las pestañas Status pages, Push keys e Backup se muestran en la misma pantalla. La copia de seguridad descarga un JSON con endpoints, páginas de estado y claves de push. Ese archivo incluye tokens, contraseñas y cabeceras; por eso existe la opción de cifrar con contraseña (AES-256-GCM). En la restauración, la pantalla muestra una vista previa de lo que cambiará antes de aplicarlo.

Para registrar muchos hosts de una sola vez, el repositorio incluye el script docs/manager-go-uptime.py, que utiliza la API de administración para importar un CSV, renombrar grupos, listar endpoints y exportar tokens de push.

Páginas de estado públicas

Una página de estado muestra solo los grupos y endpoints elegidos, sin login, mientras que el dashboard, la administración y la API siguen protegidos. Cada endpoint aparece con el estado actual, las barras de las últimas comprobaciones y el uptime de 24 horas, 7 días y 30 días. Al hacer clic en el nombre se abre una página de detalles con la gráfica de tiempo de respuesta.

status-pages:
  pages:
    - slug: publica
      title: "Status LinuxPro"
      description: "Disponibilidade dos serviços"
      groups: [sites]
      featured: [sites_linuxpro]
      show-certificate-expiration: true

La clave de un endpoint es <grupo>_<nome>, la misma utilizada en las badges. featured destaca hasta 10 endpoints en la parte superior, y show-certificate-expiration muestra cuántos días faltan para que el certificado TLS caduque. Otras opciones útiles: groups-collapsed para páginas con cientos de servicios y auth para exigir usuario y contraseña solo en esa página. Las páginas también pueden crearse desde la pestaña Status pages de la administración.

Página de status pública do Go Uptime no tema claro, com grupos de serviços e uptime

Un detalle de seguridad que la documentación deja explícito: el límite maximum-endpoints-per-page (400 por defecto) es una regla de acceso, no solo de visualización. Un endpoint que queda más allá del corte responde 404 en detalles, gráfico y badges. Aumentar el límite, por lo tanto, publica más endpoints.

Detalhes de um endpoint no Go Uptime com o gráfico de tempo de resposta

Push: copias de seguridad y tareas cron que avisan cuando se ejecutan

No todo puede comprobarse desde fuera. Un backup nocturno, un trabajo de cron o un servicio detrás de un firewall necesitan avisar que se ejecutaron. En Go Uptime, esto es un endpoint Push: no comprueba nada, solo registra los avisos y marca fallo cuando el intervalo de heartbeat pasa sin ningún push.

external-endpoints:
  - name: backup-noturno
    group: jobs
    token: "troque-por-um-token-longo-e-aleatorio"
    heartbeat:
      interval: 25h

Al final del script de copia de seguridad, basta con una línea:

curl -fsS "https://status.exemplo.com/api/push/troque-por-um-token-longo-e-aleatorio?status=up&msg=backup%20ok&ping=" >/dev/null

La respuesta es {"ok":true}; un token desconocido devuelve 404 con {"ok":false,"msg":"Monitor not found or not active."}. El parámetro status acepta up, pending (resultado amarillo, extensión de Go Uptime) o cualquier otro valor como fallo; msg aparece en el panel y en la alerta; ping es el tiempo en milisegundos.

El formato es el mismo que el de los monitores Push de Uptime Kuma: un script que ya hace push a Kuma funciona cambiando solo la dirección del servidor. Además del token por endpoint, la pestaña Push keys crea claves globales (/api/push/<chave>/<grupo_nome>), se guardan como hash SHA-256 y se pueden revocar al instante. Los endpoints activos (HTTP, TCP, etc.) también pueden aceptar push, con push.enabled: true, útil para recibir alertas de un sistema externo.

Aba de chaves de push da administração do Go Uptime

Alertas

Los proveedores de alerta son los de Gatus: Slack, Telegram, Discord, Teams, Mattermost, PagerDuty, correo electrónico, webhooks personalizados y decenas más. Un ejemplo con Telegram, que avisa también cuando el servicio vuelve:

alerting:
  telegram:
    token: "TOKEN-DO-BOT"
    id: "ID-DO-CHAT"

endpoints:
  - name: linuxpro
    group: sites
    url: "https://www.linuxpro.com.br"
    interval: 1m
    conditions:
      - "[STATUS] == 200"
    alerts:
      - type: telegram
        send-on-resolved: true

El mismo bloque alerts sirve para los endpoints Push: un backup que no ha informado dentro del intervalo de heartbeat dispara la alerta como cualquier otra falla.

MySQL, MariaDB o PostgreSQL

SQLite cubre de sobra una instancia única. Cuando la base de datos tiene que estar separada, Go Uptime admite postgres e mysql, este último compatible con MySQL 8.4+ y MariaDB 10.11+. El storage.path pasa a ser el DSN:

storage:
  type: mysql
  path: "go_uptime:${MARIADB_PASSWORD}@tcp(mariadb:3306)/go_uptime"

El repositorio tiene un ejemplo completo en .examples/docker-compose-mariadb-storage, y la documentación de almacenamiento en MySQL detalla el usuario y los permisos. El DSN sigue el formato del driver go-sql-driver/mysql; parámetros como parseTime e loc son forzados por el propio Go Uptime, y opciones como tls=true o timeout=5s se pueden añadir.

Sin Docker: binario único con systemd

Go Uptime es un binario estático, sin runtime ni bibliotecas. La instalación en Linux coloca todo en /opt/go-uptime, con un usuario propio:

VERSION=7.0.0
ARCH=amd64        # ou arm64

sudo useradd --system --home-dir /opt/go-uptime --shell /usr/sbin/nologin go-uptime
sudo install -d -o root -g go-uptime -m 0750 /opt/go-uptime /opt/go-uptime/config
sudo install -d -o go-uptime -g go-uptime -m 0750 /opt/go-uptime/data

curl -fsSL -o /tmp/go-uptime.tar.gz \
  "https://github.com/jniltinho/go-uptime/releases/download/v${VERSION}/go-uptime_${VERSION}_linux_${ARCH}.tar.gz"
sudo tar xzf /tmp/go-uptime.tar.gz -C /opt/go-uptime go-uptime
sudo chown root:go-uptime /opt/go-uptime/go-uptime && sudo chmod 0750 /opt/go-uptime/go-uptime
sudo -u go-uptime /opt/go-uptime/go-uptime version

El binario y la configuración pertenecen a root y solo son legibles por el grupo go-uptime: el servicio no puede reescribir su propio ejecutable ni el archivo que guarda el hash de la contraseña. Cree /opt/go-uptime/config/config.yaml con web.address: 127.0.0.1, web.port: 8080 e storage.path: /opt/go-uptime/data/data.db, valide con config validate e instale la unit publicada en el repositorio:

sudo curl -fsSL -o /etc/systemd/system/go-uptime.service \
  https://raw.githubusercontent.com/jniltinho/go-uptime/v7.0.0/docs/systemd/go-uptime.service
sudo systemctl daemon-reload
sudo systemctl enable --now go-uptime
curl -s http://127.0.0.1:8080/health
journalctl -u go-uptime -f

La unit viene endurecida: se ejecuta sin root, con ProtectSystem=strict y escritura habilitada solo en /opt/go-uptime/data, y valida la configuración en el ExecStartPre, lo que impide que un reinicio con YAML inválido tumbe el proceso que estaba funcionando. La única capability es CAP_NET_RAW, necesaria para endpoints ICMP; si no monitorizas por ping, puedes eliminarla. Los logs van al journal, y el nivel queda en GO_UPTIME_LOG_LEVEL. Para entender mejor este modelo de servicio, consulta nuestra guía de comandos esenciales de systemd.

Tras Nginx

El panel utiliza un flujo de eventos en tiempo real para actualizar las pantallas. Esta ruta no puede ser almacenada en búfer por el proxy, y la conexión permanece abierta durante minutos:

server {
    listen 443 ssl;
    server_name status.exemplo.com;
    # ssl_certificate ...;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location ~ ^/api/v1/(endpoints|status-pages)/.*/events$ {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
        proxy_read_timeout 7m;
    }
}

Host e X-Forwarded-Proto no son adorno: la administración usa esos encabezados para aceptar cambios provenientes de la propia dirección y para marcar la cookie de sesión como Secure.

Migrando desde Gatus

Viniendo del Gatus original, el camino es cambiar la imagen y reutilizar el config.yaml: se acepta tal cual, y los recursos nuevos son opcionales. Haz copia de seguridad de la base de datos antes y pruébalo en una copia.

Viniendo de la serie jniltinho/gatus v6, el guía de migración es aún más corto: en Docker, solo cambia el nombre de la imagen. La base de datos no necesita migración, las variables GATUS_* siguen aceptándose como alias de las nuevas GO_UPTIME_*, y una copia de seguridad hecha en v6 se restaura en v7. Lo que cambia, si dependes de ello:

  • las métricas de Prometheus pasan de gatus_ para go_uptime_; metrics-namespace: gatus mantiene los nombres antiguos;
  • o User-Agent de las comprobaciones pasa a ser go-uptime/1.0, lo cual importa si un firewall o WAF permite por esa cabecera;
  • el binario se llama go-uptime, pero la imagen se mantiene /gatus como enlace simbólico durante la serie 7.x.

Para monitorear el servidor desde dentro (CPU, memoria, disco), Go Uptime no sustituye a las métricas: combínalo con Prometheus y Node Exporter, que también puede recopilar las métricas go_uptime_* que Go Uptime expone en /metrics cuando metrics: true está en la configuración.

¿Merece la pena?

Si a tu equipo ya le gusta Gatus y solo echaba en falta una página de estado pública, registrar un monitor sin abrir el servidor o seguir las copias de seguridad mediante push, Go Uptime lo ofrece sin cambiar de herramienta ni de configuración. El proyecto es nuevo, con lanzamientos frecuentes: fija la etiqueta, ejecuta config validate antes de cada despliegue y consulta las releases antes de actualizar. El código, la documentación y los ejemplos están en el repositorio en GitHub.