Instalación de ntfy: Servidor de Notificaciones Push Self-Hosted

ntfy es un servidor de notificaciones push simple y potente basado en HTTP que permite enviar notificaciones a cualquier dispositivo mediante topics, sin necesidad de cuentas ni registro, usando solo peticiones HTTP estándar. Con soporte para autenticación, suscripción desde móviles y navegadores, e integración con cualquier herramienta que pueda hacer peticiones HTTP, ntfy es la solución ideal para recibir alertas de servidores, pipelines CI/CD y automatizaciones. Esta guía cubre la instalación completa y su integración con herramientas de monitorización.

Requisitos Previos

  • Linux (Ubuntu/Debian o CentOS/Rocky)
  • Acceso root o sudo
  • Dominio con SSL (recomendado para producción)
  • 256 MB RAM mínimo

Instalación de ntfy

# Ubuntu/Debian - Agregar el repositorio oficial
curl -fsSL https://archive.heckel.io/apt/pubkey.txt | \
    sudo gpg --dearmor -o /etc/apt/keyrings/archive.heckel.io.gpg

sudo sh -c "echo 'deb [arch=amd64 signed-by=/etc/apt/keyrings/archive.heckel.io.gpg] https://archive.heckel.io/apt debian main' \
    > /etc/apt/sources.list.d/archive.heckel.io.list"

sudo apt-get update
sudo apt-get install -y ntfy

# CentOS/Rocky Linux - Descarga directa del binario
NTFY_VERSION="2.11.0"
curl -LO "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_linux_amd64.tar.gz"
tar xzf ntfy_linux_amd64.tar.gz
sudo install -m 0755 ntfy /usr/local/bin/ntfy

# O instalar con Docker
docker run -d \
    --name ntfy \
    -p 80:80 \
    -v /var/lib/ntfy:/var/lib/ntfy \
    -v /etc/ntfy:/etc/ntfy \
    binwiederhier/ntfy serve

# Verificar la instalación
ntfy --version

Configuración del Servidor

# Crear el directorio de configuración y datos
sudo mkdir -p /etc/ntfy /var/lib/ntfy

# Crear la configuración principal
sudo cat > /etc/ntfy/server.yml << 'EOF'
# Configuración del servidor ntfy

# Dirección y puerto de escucha
listen-http: ":80"
listen-https: ":443"

# Certificados SSL (si usas ntfy directamente sin proxy)
# key-file: /etc/letsencrypt/live/ntfy.tudominio.com/privkey.pem
# cert-file: /etc/letsencrypt/live/ntfy.tudominio.com/fullchain.pem

# URL base del servidor (importante para las URLs de las notificaciones)
base-url: https://ntfy.tudominio.com

# Base de datos para mensajes (SQLite por defecto)
cache-file: /var/lib/ntfy/cache.db
cache-duration: "12h"  # Tiempo que se guardan los mensajes

# Autenticación y control de acceso
auth-file: /var/lib/ntfy/auth.db
auth-default-access: deny-all  # Denegar todo por defecto (seguro)

# Límites de uso (protección contra abuso)
visitor-subscription-limit: 30
visitor-request-limit-burst: 60
visitor-request-limit-replenish: "10s"
visitor-message-daily-limit: 250
attachment-total-size-limit: "5G"
attachment-file-size-limit: "15M"

# Caché de adjuntos
attachment-cache-dir: /var/lib/ntfy/attachments

# Log
log-level: info
log-file: /var/log/ntfy/ntfy.log
EOF

# Crear el directorio de logs
sudo mkdir -p /var/log/ntfy

# Ajustar permisos
sudo chown -R ntfy:ntfy /var/lib/ntfy /var/log/ntfy 2>/dev/null || \
    sudo chown -R nobody:nogroup /var/lib/ntfy /var/log/ntfy

Habilitar ntfy como servicio

# El instalador del paquete configura el servicio automáticamente
sudo systemctl enable ntfy
sudo systemctl start ntfy

# Para instalación manual con el binario:
cat > /etc/systemd/system/ntfy.service << 'EOF'
[Unit]
Description=ntfy push notification server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ntfy serve --config /etc/ntfy/server.yml
Restart=on-failure
User=nobody
Group=nogroup

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now ntfy

# Verificar el estado
systemctl status ntfy

# Ver que el servidor responde
curl https://ntfy.tudominio.com/v1/health

Proxy inverso con Nginx

# /etc/nginx/sites-available/ntfy
server {
    listen 80;
    server_name ntfy.tudominio.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ntfy.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/ntfy.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ntfy.tudominio.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:2586;
        proxy_http_version 1.1;

        # Necesario para SSE (Server-Sent Events)
        proxy_set_header Connection "";
        proxy_buffering off;
        proxy_cache off;

        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_connect_timeout 3m;
        proxy_send_timeout 3m;
        proxy_read_timeout 3m;

        # Para adjuntos grandes
        client_max_body_size 16M;
    }
}

Gestión de Topics y Autenticación

Con auth-default-access: deny-all, debes crear usuarios y asignar permisos explícitamente:

# Crear usuario administrador
sudo ntfy user add --role=admin admin
# Ingresar contraseña cuando se solicite

# Crear usuario para monitorización
sudo ntfy user add monitor-user

# Asignar permisos a un topic específico
sudo ntfy access monitor-user alertas-servidor rw  # lectura y escritura
sudo ntfy access monitor-user logs-servidor ro     # solo lectura

# Permitir a todos los usuarios publicar en un topic (para webhooks)
sudo ntfy access everyone webhooks-publicos wo     # solo escritura

# Ver todos los permisos configurados
sudo ntfy access

# Cambiar contraseña de un usuario
sudo ntfy user change-pass monitor-user

# Eliminar usuario
sudo ntfy user del usuario-antiguo

Uso de la API

Enviar notificaciones con curl

# Notificación básica (sin autenticación, si está permitida)
curl -d "El servidor reinició correctamente" https://ntfy.tudominio.com/alertas-servidor

# Notificación con autenticación
curl -u monitor-user:password \
    -d "Error crítico en la base de datos" \
    https://ntfy.tudominio.com/alertas-criticas

# Notificación con título, prioridad y etiquetas
curl -u monitor-user:password \
    -H "Title: Fallo en el backup" \
    -H "Priority: urgent" \
    -H "Tags: warning,backup,servidor-1" \
    -d "El backup diario falló. Revisar /var/log/backup.log" \
    https://ntfy.tudominio.com/alertas-servidor

# Notificación con enlace de acción
curl -u monitor-user:password \
    -H "Title: Deploy exitoso" \
    -H "Tags: white_check_mark,rocket" \
    -H "Click: https://mi-aplicacion.com" \
    -H "Actions: view, Ver la app, https://mi-aplicacion.com; http, Rollback, https://ci.empresa.com/rollback, method=POST" \
    -d "La versión 2.1.0 se desplegó correctamente en producción" \
    https://ntfy.tudominio.com/deploys

# Notificación programada (se entrega en el futuro)
curl -u monitor-user:password \
    -H "At: tomorrow 9am" \
    -d "Recordatorio: renovar el certificado SSL del servidor de staging" \
    https://ntfy.tudominio.com/recordatorios

# Enviar archivo adjunto
curl -u monitor-user:password \
    -T report.pdf \
    -H "Filename: reporte-semanal.pdf" \
    https://ntfy.tudominio.com/reportes

Prioridades disponibles

# Niveles de prioridad:
# 1 - min: notificación silenciosa
# 2 - low: notificación normal
# 3 - default: notificación normal con sonido
# 4 - high: notificación prominente
# 5 - urgent/max: notificación de alta prioridad que rompe el modo silencioso

curl -u monitor-user:password \
    -H "Priority: 5" \
    -H "Title: CRÍTICO: Servidor caído" \
    -d "El servidor de producción no responde" \
    https://ntfy.tudominio.com/alertas-criticas

Aplicación Móvil

ntfy tiene aplicaciones nativas para iOS y Android:

Android: https://play.google.com/store/apps/details?id=io.heckel.ntfy
         O F-Droid para versión open source

iOS: https://apps.apple.com/app/ntfy/id1625396347

Configurar servidor self-hosted en la app

  1. Abrir ntfy > Configuración > Servidor predeterminado
  2. Ingresar: https://ntfy.tudominio.com
  3. Agregar credenciales: Usuario y contraseña configurados
# Suscribirse a un topic
# En la app: agregar suscripción → ingresar el nombre del topic

# También puedes suscribirte desde el navegador web
# https://ntfy.tudominio.com/alertas-servidor
# La interfaz web muestra las notificaciones en tiempo real

Integración con Herramientas

Alertas de Grafana

# En Grafana: Alerting > Contact Points > New contact point
# Tipo: webhook
# URL: https://ntfy.tudominio.com/alertas-grafana
# Method: POST
# Headers:
#   Authorization: Basic base64(usuario:password)
#   Title: Alerta de Grafana
#   Priority: high

Scripts de monitorización

# Script para alertas de uso de disco
cat > /usr/local/bin/check-disk.sh << 'EOF'
#!/bin/bash
# Verificar uso de disco y alertar via ntfy

NTFY_URL="https://ntfy.tudominio.com/servidor-produccion"
NTFY_TOKEN="tu-token-de-autenticacion"
UMBRAL=85

while IFS= read -r line; do
    PORCENTAJE=$(echo "$line" | awk '{print $5}' | sed 's/%//')
    PARTICION=$(echo "$line" | awk '{print $6}')
    
    if [ "$PORCENTAJE" -gt "$UMBRAL" ]; then
        curl -s \
            -H "Authorization: Bearer $NTFY_TOKEN" \
            -H "Title: Disco casi lleno en $(hostname)" \
            -H "Priority: high" \
            -H "Tags: warning,harddisk" \
            -d "La partición $PARTICION está al ${PORCENTAJE}% de uso" \
            "$NTFY_URL"
    fi
done < <(df -h | grep -E '^/dev/' | grep -v 'tmpfs')
EOF

chmod +x /usr/local/bin/check-disk.sh

# Agregar al crontab (verificar cada hora)
echo "0 * * * * root /usr/local/bin/check-disk.sh" > /etc/cron.d/check-disk

Integración con systemd (alertas de servicios caídos)

# Crear handler de fallos de systemd que notifica via ntfy
cat > /etc/systemd/system/[email protected] << 'EOF'
[Unit]
Description=Notificación ntfy para fallos de %i

[Service]
Type=oneshot
ExecStart=/usr/bin/curl \
    -u monitor:password \
    -H "Title: Servicio caído en %H" \
    -H "Priority: urgent" \
    -H "Tags: sos,red_circle" \
    -d "El servicio %i falló en el servidor %H" \
    https://ntfy.tudominio.com/alertas-servidor
EOF

# Agregar el handler a cualquier servicio que quieras monitorizar
# En /etc/systemd/system/mi-servicio.service:
# [Unit]
# OnFailure=ntfy-failure@%n.service

systemctl daemon-reload

# Activar para un servicio existente con override
mkdir -p /etc/systemd/system/nginx.service.d/
cat > /etc/systemd/system/nginx.service.d/ntfy.conf << 'EOF'
[Unit]
OnFailure=ntfy-failure@%n.service
EOF

systemctl daemon-reload

Solución de Problemas

Las notificaciones no llegan al móvil

# Verificar que la app está suscrita al topic correcto
# y que el servidor está configurado

# Verificar que el servidor responde
curl https://ntfy.tudominio.com/v1/health

# Probar la suscripción desde curl (modo SSE)
curl -u usuario:password \
    https://ntfy.tudominio.com/mi-topic/json
# Dejar corriendo y enviar una notificación de prueba desde otra terminal

Error de autenticación al publicar

# Verificar los permisos del usuario
sudo ntfy access

# Verificar que el usuario existe
sudo ntfy user list

# Probar con credenciales explícitas
curl -v -u usuario:password \
    -d "Prueba de autenticación" \
    https://ntfy.tudominio.com/mi-topic

El servidor no arranca

# Ver los logs de error
journalctl -u ntfy -n 50

# Verificar la sintaxis del archivo de configuración
ntfy serve --config /etc/ntfy/server.yml --check-config

# Verificar permisos del directorio de datos
ls -la /var/lib/ntfy/

Conclusión

ntfy es la herramienta de notificaciones más sencilla de integrar en entornos DevOps: cualquier script que pueda hacer una petición HTTP puede enviar notificaciones push a móviles, navegadores y clientes de escritorio. Su arquitectura basada en topics y SSE es eficiente incluso con miles de suscriptores, y el control de acceso granular por topic permite usarla de forma segura en producción. La combinación de servidor self-hosted, aplicación móvil nativa y API HTTP estándar la hace una pieza fundamental en cualquier stack de monitorización y automatización.