Instalación de Gatus: Dashboard de Salud para Endpoints
Gatus es una herramienta de monitoreo de salud de endpoints ligera y declarativa que comprueba periódicamente URLs, APIs, bases de datos y servicios TCP/UDP, generando una página de estado pública y enviando alertas cuando algo falla. Con su configuración en YAML y su imagen Docker de menos de 20 MB, Gatus es fácil de desplegar y mantener sin las complejidades de soluciones más pesadas como Nagios o Zabbix. Esta guía cubre la instalación, configuración de checks, condiciones de salud y la integración con Slack, PagerDuty y email.
Requisitos Previos
- Ubuntu 20.04/22.04 o CentOS 8+/Rocky Linux 8+
- Docker (recomendado) o binario Go
- Puerto 8080 disponible para la interfaz web
- Acceso a los endpoints que quieres monitorear
Instalación de Gatus
Instalación con Docker
# Crear directorio de configuración
mkdir -p /opt/gatus
# Crear el archivo de configuración (ver siguiente sección)
nano /opt/gatus/config.yaml
# Ejecutar Gatus con Docker
docker run -d \
--name gatus \
-p 8080:8080 \
-v /opt/gatus/config.yaml:/config/config.yaml:ro \
twinproduction/gatus:latest
# Verificar que está corriendo
docker logs gatus
curl http://localhost:8080/health
Instalación con Docker Compose
# /opt/gatus/docker-compose.yml
version: "3.8"
services:
gatus:
image: twinproduction/gatus:latest
container_name: gatus
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config.yaml:/config/config.yaml:ro
environment:
SLACK_WEBHOOK_URL: https://hooks.slack.com/services/TU/WEBHOOK/URL
PAGERDUTY_INTEGRATION_KEY: tu_integration_key
docker compose up -d
Instalación del binario
# Descargar el binario precompilado
GATUS_VERSION=5.10.0
wget "https://github.com/TwiN/gatus/releases/download/v${GATUS_VERSION}/gatus_linux_amd64.tar.gz" -P /tmp
cd /tmp && tar xzf gatus_linux_amd64.tar.gz
sudo mv gatus /usr/local/bin/
sudo chmod +x /usr/local/bin/gatus
# Crear servicio systemd
sudo tee /etc/systemd/system/gatus.service > /dev/null <<EOF
[Unit]
Description=Gatus Health Dashboard
After=network.target
[Service]
Type=simple
User=gatus
ExecStart=/usr/local/bin/gatus --config=/opt/gatus/config.yaml
Restart=on-failure
Environment="GATUS_CONFIG_PATH=/opt/gatus/config.yaml"
[Install]
WantedBy=multi-user.target
EOF
sudo useradd -r -s /bin/false gatus
sudo mkdir -p /opt/gatus
sudo chown -R gatus:gatus /opt/gatus
sudo systemctl daemon-reload
sudo systemctl enable gatus --now
Configuración Básica
El archivo de configuración /opt/gatus/config.yaml:
# /opt/gatus/config.yaml
# Configuración de almacenamiento (para historial de uptime)
storage:
type: sqlite
path: /data/gatus.db
# Configuración del servidor web
web:
port: 8080
# Métricas de Prometheus
metrics: true
# Configuración de alertas globales
alerting:
slack:
webhook-url: "$SLACK_WEBHOOK_URL"
default-alert:
description: "Un endpoint está fallando"
send-on-resolved: true
failure-threshold: 3
success-threshold: 2
# Definición de los endpoints a monitorear
endpoints:
- name: Sitio Web Principal
url: https://www.tudominio.com
interval: 1m
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 2000"
alerts:
- type: slack
- name: API de Producción
url: https://api.tudominio.com/health
interval: 30s
conditions:
- "[STATUS] == 200"
- "[BODY].status == healthy"
- "[RESPONSE_TIME] < 500"
alerts:
- type: slack
failure-threshold: 2
Endpoints y Condiciones
Gatus evalúa condiciones para determinar si un endpoint está saludable:
endpoints:
# Check HTTP básico
- name: API REST
url: https://api.ejemplo.com/v1/status
method: GET
interval: 30s
headers:
Authorization: "Bearer tu-token"
Content-Type: "application/json"
conditions:
- "[STATUS] == 200" # Código HTTP debe ser 200
- "[RESPONSE_TIME] < 1000" # Tiempo de respuesta < 1 segundo
- "[BODY].status == ok" # Campo 'status' en JSON = 'ok'
- "[BODY].version != " # El campo 'version' no debe estar vacío
- "[CERTIFICATE_EXPIRATION] > 168h" # Certificado SSL válido > 7 días
# Check POST con body JSON
- name: API de Autenticación
url: https://auth.ejemplo.com/api/check
method: POST
body: |
{"ping": true}
headers:
Content-Type: "application/json"
interval: 1m
conditions:
- "[STATUS] == 200"
- "[BODY].pong == true"
# Check TCP (para servicios que no son HTTP)
- name: PostgreSQL
url: tcp://postgres.interno:5432
interval: 30s
conditions:
- "[CONNECTED] == true"
# Check DNS
- name: DNS externo
url: https://8.8.8.8
dns:
query-name: api.ejemplo.com
query-type: A
interval: 5m
conditions:
- "[DNS_RCODE] == NOERROR"
- "[BODY] == 93.184.216.34" # IP esperada
# Check ICMP (ping)
- name: Ping al servidor de base de datos
url: icmp://192.168.1.10
interval: 30s
conditions:
- "[CONNECTED] == true"
Condiciones disponibles:
| Condición | Descripción |
|---|---|
[STATUS] | Código de respuesta HTTP |
[RESPONSE_TIME] | Tiempo de respuesta en ms |
[BODY] | Cuerpo de la respuesta (soporta JSONPath) |
[BODY].campo | Campo específico del JSON de respuesta |
[CONNECTED] | Si se pudo conectar (TCP/ICMP) |
[CERTIFICATE_EXPIRATION] | Tiempo hasta expirar el certificado SSL |
[DNS_RCODE] | Código de respuesta DNS |
Checks Avanzados
endpoints:
# Verificar que el cuerpo contiene una cadena
- name: Página de Login
url: https://app.ejemplo.com/login
interval: 2m
conditions:
- "[STATUS] == 200"
- "[BODY] pat (Login|Sign in)" # Expresión regular
# Check con autenticación básica
- name: Panel de Admin (protegido)
url: https://admin.ejemplo.com/health
interval: 5m
headers:
Authorization: "Basic dXNlcjpwYXNz" # base64 de "user:pass"
conditions:
- "[STATUS] == 200"
# Agrupar endpoints relacionados
- name: API Gateway
group: Infraestructura
url: https://gateway.ejemplo.com/health
interval: 30s
conditions:
- "[STATUS] == 200"
- name: Servicio de Pagos
group: Infraestructura
url: https://pagos.ejemplo.com/health
interval: 30s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 500"
# Reintentos antes de marcar como fallido
- name: Endpoint inestable
url: https://servicio-inestable.ejemplo.com/health
interval: 1m
ui:
description: "Servicio con alta latencia ocasional"
conditions:
- "[STATUS] == 200"
alerts:
- type: slack
failure-threshold: 5 # Fallar 5 veces antes de alertar
success-threshold: 3 # 3 éxitos consecutivos para resolver
Alertas y Notificaciones
alerting:
# Slack
slack:
webhook-url: "$SLACK_WEBHOOK_URL"
default-alert:
send-on-resolved: true
failure-threshold: 3
success-threshold: 2
# PagerDuty
pagerduty:
integration-key: "$PAGERDUTY_INTEGRATION_KEY"
default-alert:
send-on-resolved: true
failure-threshold: 2
success-threshold: 1
# Email via SMTP
email:
from: "[email protected]"
username: "[email protected]"
password: "$EMAIL_PASSWORD"
host: smtp.gmail.com
port: 587
to: "[email protected]"
default-alert:
send-on-resolved: true
failure-threshold: 3
# Telegram
telegram:
token: "$TELEGRAM_BOT_TOKEN"
id: "$TELEGRAM_CHAT_ID"
default-alert:
send-on-resolved: true
failure-threshold: 2
# Webhook genérico
custom:
url: "https://webhook.tudominio.com/alertas"
method: POST
body: |
{
"text": "[ALERT_TRIGGERED] - [ENDPOINT_NAME] is [RESULT_CONDITION]"
}
headers:
Content-Type: "application/json"
Authorization: "Bearer TU_TOKEN"
Página de Estado
Gatus genera automáticamente una página de estado pública en http://tu-ip:8080.
Personalización de la interfaz:
# En config.yaml
ui:
title: "Estado de Servicios - Mi Empresa"
description: "Monitoreo en tiempo real de todos nuestros servicios"
header: "Mi Empresa - Status Page"
logo: "https://tudominio.com/logo.png"
link: "https://tudominio.com"
buttons:
- name: "Portal"
link: "https://portal.tudominio.com"
- name: "Documentación"
link: "https://docs.tudominio.com"
# Configurar Nginx para servir Gatus con dominio propio
server {
listen 443 ssl;
server_name status.tudominio.com;
ssl_certificate /etc/letsencrypt/live/status.tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/status.tudominio.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Métricas de Prometheus
Con metrics: true en la configuración, Gatus expone métricas en /metrics:
# Ver métricas de Gatus
curl http://localhost:8080/metrics | grep gatus
# Métricas disponibles:
# gatus_results_total - Número total de checks ejecutados
# gatus_results_duration_seconds - Tiempo de respuesta de los checks
# gatus_results_connected - Si el endpoint está conectado (1/0)
# gatus_results_code_xxx_total - Conteo de respuestas por código HTTP
# Configuración de Prometheus para scrapear Gatus
# En /etc/prometheus/prometheus.yml
scrape_configs:
- job_name: 'gatus'
static_configs:
- targets: ['gatus:8080']
metrics_path: /metrics
Solución de Problemas
Gatus no arranca:
# Ver logs del contenedor
docker logs gatus --tail 50
# Verificar la sintaxis del archivo de configuración
docker run --rm \
-v /opt/gatus/config.yaml:/config/config.yaml:ro \
twinproduction/gatus validate
# El error más común es una indentación incorrecta en el YAML
python3 -c "import yaml; yaml.safe_load(open('/opt/gatus/config.yaml'))"
Los endpoints siempre aparecen como fallidos:
# Verificar conectividad desde el contenedor/servidor de Gatus
docker exec gatus curl -v https://tu-endpoint.com/health
# Si el endpoint requiere certificados específicos:
docker exec gatus curl --cacert /ruta/ca.pem https://endpoint-interno.com
Las alertas no llegan:
# Verificar las variables de entorno de Slack
docker exec gatus env | grep SLACK
# Verificar el webhook de Slack manualmente
curl -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"text": "Prueba de Gatus"}'
# Revisar los logs de Gatus para errores de alerta
docker logs gatus | grep -i "alert\|error"
La página de estado muestra datos incorrectos:
# Ver el estado actual de todos los endpoints via API
curl http://localhost:8080/api/v1/endpoints/statuses | python3 -m json.tool
# Forzar un check inmediato (no disponible via API, reiniciar el servicio)
docker restart gatus
Conclusión
Gatus es una solución de monitoreo de endpoints elegante que prioriza la simplicidad sin sacrificar funcionalidades esenciales como las alertas multicanel, el historial de uptime y la página de estado pública. La configuración declarativa en YAML facilita el versionado en Git y la gestión como código, mientras que el uso de variables de entorno para datos sensibles mantiene las credenciales fuera del repositorio. Para la mayoría de equipos pequeños y medianos, Gatus cubre el 90% de las necesidades de monitoreo de disponibilidad con una fracción del esfuerzo operativo de soluciones más complejas.


