Levantar tu propio server ntfy
El plugin ntfy puede publicar contra
https://ntfy.sh (el server público) o contra tu propio server.
Autohospedar te da:
- Topics privados con ACL nativa.
- Sin límite de 250 mensajes/día por IP.
- Ancho de banda tuyo — el server público tiene tráfico compartido.
- Menos superficie de vigilancia — los títulos y mensajes no pasan por infraestructura de terceros.
El binary corre en cualquier Debian/Ubuntu y usa ~20 MB de RAM en idle. Este runbook cubre el setup en un LXC de Proxmox; el proceso en un VPS o en Docker es equivalente.
LXC en Proxmox
1. Crear el container
Desde el host Proxmox (o pct en SSH):
pct create 111 local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst \
--hostname ntfy \
--memory 256 --swap 128 --cores 1 \
--rootfs local-lvm:3 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 1 --features nesting=1 --onboot 1 \
--ssh-public-keys /root/.ssh/authorized_keys
pct start 111
Verifica que el LXC tiene IP:
pct exec 111 -- ip -4 addr show eth0 | grep inet
2. Instalar ntfy
El repo apt oficial vive en archive.ntfy.sh. Si tu red interna no
resuelve dominios externos, pon DNS público en /etc/resolv.conf
antes de instalar:
pct exec 111 -- bash -c '
echo "nameserver 1.1.1.1" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
apt update && apt install -y curl wget
'
Descarga el .deb desde el release de GitHub (más rápido y no depende
del repo apt):
NTFY_VERSION=v2.13.0
pct exec 111 -- bash -c "
wget -q https://github.com/binwiederhier/ntfy/releases/download/$NTFY_VERSION/ntfy_2.13.0_linux_amd64.deb -O /tmp/ntfy.deb
apt install -y /tmp/ntfy.deb
"
3. Configurar el server
Edita /etc/ntfy/server.yml:
# Server config
base-url: https://ntfy.tudominio.com # el dominio público que verá el usuario
listen-http: :80
cache-file: /var/cache/ntfy/cache.db
cache-duration: 12h # cuánto guarda mensajes para suscriptores nuevos
attachment-cache-dir: /var/cache/ntfy/attachments
behind-proxy: true # ntfy corre detrás de Cloudflare Tunnel
# Authentication (opcional pero recomendado en public)
auth-file: /var/lib/ntfy/auth.db
auth-default-access: read-write # cambialo a deny-all para forzar auth
enable-signup: false
enable-login: true
enable-reservations: true # permite delay + topic ownership
# Web UI en /app
web-root: app
Ajustes de permisos y arranque:
pct exec 111 -- bash -c '
mkdir -p /var/cache/ntfy /var/lib/ntfy
chown -R ntfy:ntfy /var/cache/ntfy /var/lib/ntfy
systemctl enable --now ntfy
systemctl status ntfy --no-pager | head -8
'
4. Exponer con Cloudflare Tunnel
Si ya tienes un tunnel corriendo, agrega una ruta que apunte al LXC. Si usas la API de Cloudflare (como en el runbook de este framework):
# Con CLOUDFLARE_API_TOKEN y CLOUDFLARE_ACCOUNT_ID exportados en el env
LXC_IP=192.168.1.41 # IP del LXC 111
TUNNEL_ID=... # el UUID de tu tunnel
# Agrega la ruta a tu ingress list (via API PUT a /cfd_tunnel/{id}/configurations)
Y crea el DNS record CNAME:
ntfy.tudominio.com CNAME <TUNNEL_ID>.cfargotunnel.com (proxied)
Verifica:
curl -sS -X POST "https://ntfy.tudominio.com/test-topic" \
-H "Title: Hola" \
-d "Server funcionando" \
-w "\nHTTP %{http_code}\n"
Debe devolver HTTP 200 y un JSON {"id":"…","event":"message",…}.
5. Conectar al framework
En el CMS → Configuración → ntfy — notificaciones push → Configuración:
- Servidor ntfy:
https://ntfy.tudominio.com - Token: (opcional) el token que emitiste con
ntfy user add …. - Prefijo: si compartís el server con varias instalaciones,
pon un prefijo (
empresa-,cliente-) para evitar colisiones.
Y en el config.php del plugin agrega tu host al allowlist:
return [
'extra_hosts' => ['ntfy.tudominio.com'],
// o bien:
'extra_suffixes' => ['.tudominio.com'],
];
Esto abre el guard NtfyEngine::isTrustedServerUrl para tu host — sin
esta línea el conector se niega a publicar (protege contra SSRF).
Configuración con Docker
Alternativa sin Proxmox:
docker run -d --name ntfy \
-p 80:80 \
-v ntfy-cache:/var/cache/ntfy \
-v ntfy-lib:/var/lib/ntfy \
-e TZ=America/Santiago \
binwiederhier/ntfy serve
Después el mismo tunnel/DNS/firewall.
Users y ACL
Con auth-default-access: deny-all en el yaml, los suscriptores y
publishers necesitan credenciales:
# Crear un admin
ntfy user add --role=admin admin
# Crear un usuario publisher (sólo escribe)
ntfy user add publisher-aurora
ntfy access publisher-aurora aurora-* write-only
# Crear un usuario reader (sólo lee un topic específico)
ntfy user add cliente-42
ntfy access cliente-42 aurora-cliente-42 read-only
El framework usa las credenciales del admin (token) para publicar. El subscriber final entra con su propia credencial o suscribe a un topic público (sin auth).
Backup
Los datos viven en:
/var/cache/ntfy/(mensajes en cache, se puede perder)/var/lib/ntfy/(auth.db, ACL, reservations — esto sí backup)
Backup diario del segundo directorio con tar o el mecanismo que uses
para el resto del stack.
Monitoreo
ntfy expone metrics en /metrics (formato Prometheus) si activas
enable-metrics: true. Útil para trackear publish rate y suscriptores
activos.
¿Qué sigue?
- Plugin ntfy — para crear topics y ver la actividad desde el CMS.
- Notification Manager — para disparar ntfy con reglas visuales sobre transiciones de workflow.