Gotify: Servidor de Notificaciones Push Self-Hosted
Gotify es un servidor de notificaciones push self-hosted simple y ligero que proporciona una API REST para enviar mensajes y una interfaz web con WebSocket para recibirlos en tiempo real, con aplicación nativa de Android incluida. Es la opción ideal para equipos que necesitan un sistema de notificaciones privado y sin dependencias de servicios externos como Firebase Cloud Messaging. Esta guía cubre la instalación con Docker, gestión de aplicaciones y integración con sistemas de monitorización.
Requisitos Previos
- Linux con Docker instalado (o acceso al binario)
- 256 MB RAM mínimo
- Nginx como proxy inverso (recomendado)
- Dominio con SSL para producción
Instalación con Docker
# Crear directorio de datos persistentes
mkdir -p /opt/gotify/data
# Ejecutar Gotify con Docker
docker run -d \
--name gotify \
--restart unless-stopped \
-p 127.0.0.1:8080:80 \
-v /opt/gotify/data:/app/data \
-e TZ=Europe/Madrid \
gotify/server:latest
# Verificar que está corriendo
docker ps | grep gotify
docker logs gotify --tail=20
Docker Compose (recomendado)
# /opt/gotify/docker-compose.yml
version: '3'
services:
gotify:
image: gotify/server:latest
container_name: gotify
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./data:/app/data
environment:
GOTIFY_DEFAULTUSER_NAME: admin
GOTIFY_DEFAULTUSER_PASS: AdminPassword123!
GOTIFY_PASSSTRENGTH: 12
GOTIFY_UPLOADEDIMAGESDIR: data/images
GOTIFY_PLUGINSDIR: data/plugins
GOTIFY_REGISTRATION: "false"
TZ: Europe/Madrid
# Base de datos SQLite por defecto
# Para producción, considera MySQL/PostgreSQL:
# GOTIFY_DATABASE_DIALECT: postgres
# GOTIFY_DATABASE_CONNECTION: "host=db port=5432 user=gotify password=pass dbname=gotify"
cd /opt/gotify
docker compose up -d
# Verificar el inicio
docker compose logs -f
Proxy inverso con Nginx
cat > /etc/nginx/sites-available/gotify << 'EOF'
server {
listen 80;
server_name notificaciones.tudominio.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name notificaciones.tudominio.com;
ssl_certificate /etc/letsencrypt/live/notificaciones.tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/notificaciones.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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support (necesario para recibir notificaciones en tiempo real)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
}
}
EOF
ln -s /etc/nginx/sites-available/gotify /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
# Obtener certificado SSL
certbot --nginx -d notificaciones.tudominio.com
Instalación del Binario
Para servidores sin Docker:
# Descargar el binario de Gotify
GOTIFY_VERSION="2.4.0"
curl -LO "https://github.com/gotify/server/releases/download/v${GOTIFY_VERSION}/gotify-linux-amd64.zip"
unzip gotify-linux-amd64.zip
mv gotify-linux-amd64 /usr/local/bin/gotify
chmod +x /usr/local/bin/gotify
# Crear directorio de datos
mkdir -p /var/lib/gotify
# Crear usuario del sistema
useradd --system --no-create-home --shell /bin/false gotify
chown gotify:gotify /var/lib/gotify
# Crear archivo de configuración
cat > /etc/gotify/config.yml << 'EOF'
server:
keepaliveperiodseconds: 0
listenaddr: 127.0.0.1
port: 8080
ssl:
enabled: false
database:
dialect: sqlite3
connection: /var/lib/gotify/gotify.db
defaultuser:
name: admin
pass: AdminPassword123!
passstrength: 12
uploadedimagesdir: /var/lib/gotify/images
pluginsdir: /var/lib/gotify/plugins
registration: false
EOF
# Crear servicio systemd
cat > /etc/systemd/system/gotify.service << 'EOF'
[Unit]
Description=Gotify Push Notification Server
After=network.target
[Service]
Type=simple
User=gotify
Group=gotify
WorkingDirectory=/var/lib/gotify
ExecStart=/usr/local/bin/gotify --config /etc/gotify/config.yml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now gotify
systemctl status gotify
Gestión de Aplicaciones y Clientes
En Gotify, la arquitectura se basa en:
- Aplicaciones (Apps): fuentes de mensajes, cada una con su token de API
- Clientes (Clients): consumidores de mensajes (dispositivos móviles, web, scripts)
Gestión desde la interfaz web
- Accede a
https://notificaciones.tudominio.com - Usuario:
admin, Contraseña: la configurada en el setup - Apps > Create Application: crear una nueva fuente de mensajes
Gestión via API
# Autenticarse y obtener token de usuario (para gestión)
# En la interfaz web: Clients > Create Client
# Copiar el token generado
CLIENT_TOKEN="tu-token-de-cliente"
# Listar todas las aplicaciones
curl https://notificaciones.tudominio.com/application \
-H "X-Gotify-Key: $CLIENT_TOKEN" | jq '.[]'
# Crear una nueva aplicación para un servidor
APP_RESPONSE=$(curl -s -X POST https://notificaciones.tudominio.com/application \
-H "X-Gotify-Key: $CLIENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Servidor Produccion",
"description": "Alertas del servidor de producción principal"
}')
echo $APP_RESPONSE | jq '.'
APP_TOKEN=$(echo $APP_RESPONSE | jq -r '.token')
echo "Token de la aplicación: $APP_TOKEN"
# Listar todos los mensajes
curl "https://notificaciones.tudominio.com/message?limit=20" \
-H "X-Gotify-Key: $CLIENT_TOKEN" | jq '.'
# Eliminar un mensaje
curl -X DELETE https://notificaciones.tudominio.com/message/42 \
-H "X-Gotify-Key: $CLIENT_TOKEN"
# Eliminar todos los mensajes de una aplicación
curl -X DELETE https://notificaciones.tudominio.com/application/1/message \
-H "X-Gotify-Key: $CLIENT_TOKEN"
Uso de la API REST
Una vez que tienes el token de una aplicación, puedes enviar mensajes:
APP_TOKEN="token-de-tu-aplicacion"
GOTIFY_URL="https://notificaciones.tudominio.com"
# Enviar mensaje básico
curl -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Servidor en línea",
"message": "El servidor web arrancó correctamente",
"priority": 2
}'
# Enviar mensaje con prioridad alta
curl -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "ERROR: Base de datos no responde",
"message": "PostgreSQL dejó de responder a las 14:32. Revisar logs en /var/log/postgresql/",
"priority": 9
}'
# Enviar mensaje con extras (markdown y enlaces)
curl -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Reporte de Backup",
"message": "## Backup Completado\n\n- **Estado**: Exitoso\n- **Archivos**: 15,234\n- **Tamaño**: 2.3 GB\n- **Duración**: 4m 32s",
"priority": 3,
"extras": {
"client::display": {
"contentType": "text/markdown"
}
}
}'
Prioridades y Extras de Mensajes
Niveles de prioridad
# Prioridades de Gotify (0-10):
# 0: Min - notificación silenciosa
# 1-3: Low - notificación normal
# 4-7: Normal - notificación con sonido
# 8-10: High - notificación prominente, puede romper el silencio
# En la app Android de Gotify:
# Las prioridades altas (>= 8) activan el canal de máxima importancia
Extras para contenido enriquecido
# Mensaje con enlace clickeable
curl -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Deploy completado",
"message": "La versión 2.1.0 está en producción",
"priority": 5,
"extras": {
"client::notification": {
"click": {"url": "https://miapp.tudominio.com"}
}
}
}'
# Mensaje con BigPicture (imagen en la notificación Android)
curl -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Grafico de métricas",
"message": "Rendimiento del último día",
"priority": 3,
"extras": {
"android::action": {
"onReceive": {"intentUrl": "https://grafana.tudominio.com/dashboard"}
},
"client::display": {
"contentType": "text/markdown"
}
}
}'
Integración con Monitorización
Alertas de Uptime Kuma
# En Uptime Kuma: Settings > Notifications > Add Notification
# Tipo: Gotify
# Server URL: https://notificaciones.tudominio.com
# Token: token de la aplicación de Uptime Kuma
# Priority: 8 (para alertas de caídas)
Script para alertas de sistema
cat > /usr/local/bin/gotify-alert.sh << 'EOF'
#!/bin/bash
# Script helper para enviar alertas a Gotify
GOTIFY_URL="https://notificaciones.tudominio.com"
APP_TOKEN="${GOTIFY_TOKEN:-}" # Token desde variable de entorno o parámetro
TITULO="${1:-Sin título}"
MENSAJE="${2:-Sin mensaje}"
PRIORIDAD="${3:-5}"
if [ -z "$APP_TOKEN" ]; then
echo "Error: GOTIFY_TOKEN no está configurado"
exit 1
fi
RESPUESTA=$(curl -s -w "\n%{http_code}" -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $APP_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"$TITULO\",
\"message\": \"$MENSAJE\",
\"priority\": $PRIORIDAD
}")
HTTP_CODE=$(echo "$RESPUESTA" | tail -1)
if [ "$HTTP_CODE" = "200" ]; then
echo "Notificación enviada correctamente"
else
echo "Error al enviar notificación: HTTP $HTTP_CODE"
exit 1
fi
EOF
chmod +x /usr/local/bin/gotify-alert.sh
# Uso del script
export GOTIFY_TOKEN="tu-app-token"
gotify-alert.sh "Backup completado" "El backup de producción finalizó correctamente" 3
gotify-alert.sh "ERROR: Disco lleno" "El disco /dev/sda1 está al 98%" 9
Integración con Grafana
# En Grafana: Alerting > Contact Points > New contact point
# Tipo: webhook
# URL: https://notificaciones.tudominio.com/message?token=TU_APP_TOKEN
# Method: POST
# Headers: Content-Type: application/json
# Configurar el payload template en Grafana:
{
"title": "Alerta: {{ .GroupLabels.alertname }}",
"message": "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}",
"priority": 8
}
Alertas de cron jobs
# Wrapper para cron que notifica en caso de fallo
cat > /usr/local/bin/cron-with-gotify.sh << 'EOF'
#!/bin/bash
# Ejecutar un comando y notificar via Gotify si falla
COMANDO="$*"
GOTIFY_URL="https://notificaciones.tudominio.com"
GOTIFY_TOKEN="tu-app-token"
SALIDA=$(eval "$COMANDO" 2>&1)
CODIGO=$?
if [ $CODIGO -ne 0 ]; then
curl -s -X POST "$GOTIFY_URL/message" \
-H "X-Gotify-Key: $GOTIFY_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"Error en cron: $(hostname)\",
\"message\": \"Comando: $COMANDO\nCódigo de salida: $CODIGO\nSalida:\n$SALIDA\",
\"priority\": 7
}"
exit $CODIGO
fi
EOF
chmod +x /usr/local/bin/cron-with-gotify.sh
# Uso en crontab:
# 0 3 * * * root cron-with-gotify.sh /usr/local/bin/backup.sh
Solución de Problemas
El servidor no arranca
# Con Docker:
docker logs gotify --tail=50
# Con el binario:
journalctl -u gotify -n 50
# Problemas comunes:
# - Puerto 8080 ya en uso: cambiar el puerto en la configuración
# - Permisos del directorio de datos: chown -R gotify:gotify /var/lib/gotify
Los mensajes no llegan a la app Android
# Gotify usa WebSocket para la entrega en tiempo real
# Verificar que el proxy Nginx está configurado para WebSocket:
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
# Verificar conectividad WebSocket
curl -I -H "Upgrade: websocket" -H "Connection: Upgrade" \
https://notificaciones.tudominio.com/stream?token=CLIENT_TOKEN
# En la app Android: verificar que la URL del servidor es correcta
# y que incluye https://
Error 401 al enviar mensajes
# Verificar que estás usando el token correcto
# Para enviar mensajes: token de la APLICACIÓN (App token)
# Para gestionar: token del CLIENTE (Client token)
# Listar aplicaciones y sus tokens (necesitas client token)
curl https://notificaciones.tudominio.com/application \
-H "X-Gotify-Key: $CLIENT_TOKEN" | jq '.[] | {id, name, token}'
Conclusión
Gotify ofrece un sistema de notificaciones push privado y sin dependencias de Google o Apple con una arquitectura simple basada en WebSocket. Su combinación de API REST fácil de integrar, aplicación Android nativa, interfaz web y soporte para plugins lo hace adecuado tanto para alertas de servidores como para notificaciones de aplicaciones en producción. La instalación con Docker en menos de 5 minutos y el modelo de aplicaciones/clientes lo convierten en una pieza sencilla pero potente en cualquier stack de operaciones.


