tuxvador@blog:~/blog/fr/self-hosted-push-notifications-ntfy$

~/blog/fr/self-hosted-push-notifications-ntfy

Notifications Push Auto-Hébergées avec ntfy

4 min de lectureRead in English →

#self-hosting#linux#automation#monitoring#security

Toute pile auto-hébergée finit par avoir besoin de vous dire quelque chose. Un disque se remplit, un flux de caméra tombe, quelqu’un rejoint le WiFi invité, CrowdSec bannit une IP. L’email est trop lent à lire et trop facile à ignorer, et un service push cloud signifie que vos alertes — qui contiennent vos hostnames, vos IP, vos noms de services — traversent l’infrastructure de quelqu’un d’autre.

ntfy est un unique binaire Go qui fait de la publication/abonnement de notifications push en HTTP simple, avec des applications pour Android et iOS. C’est la pièce la moins intéressante de ma pile de surveillance et celle que j’utilise le plus.

Installer et configurer

apt install ntfy

Le paquet de la distribution place la configuration du serveur dans /etc/ntfy/server.yml. Les valeurs par défaut sont grandes ouvertes, donc la configuration consiste surtout à fermer des choses :

base-url: "https://ntfy.example.org"

listen-http: "0.0.0.0:2586"
behind-proxy: true

cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "24h"

auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"

enable-signup: false
enable-login: true
enable-reservations: false

attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-total-size-limit: "1G"
attachment-file-size-limit: "5M"
attachment-expiry-duration: "24h"

auth-default-access: deny-all est le réglage qui compte. Le modèle par défaut de ntfy est ouvert : quiconque connaît le nom d’un topic peut le lire et y publier. Les noms de topics sont devinables — alerts, camera, backup — donc « ouvert » veut dire « public » d’une manière qui ne devient évidente que quand quelqu’un d’autre le trouve. deny-all inverse la logique : chaque topic exige une autorisation explicite d’un utilisateur ou d’un token, et rien n’est lisible en devinant.

enable-signup: false ferme le point d’entrée d’inscription, qui sinon laisse n’importe qui créer un compte sur votre serveur. Et behind-proxy: true compte quand ntfy est derrière nginx : sans lui, le rate limiter voit chaque requête comme venant de l’IP de votre proxy, donc un seul client bruyant limite tout le monde. Avec, ntfy fait confiance à X-Forwarded-For et applique les limites par client réel.

N’exposez pas le port

ntfy écoute sur 2586, et ce port ne doit pas être joignable depuis Internet. Placez-le derrière votre proxy inverse et restreignez-le au pare-feu :

# seul le proxy inverse peut joindre ntfy
chain input {
  ip saddr { 10.99.99.11 } tcp dport 2586 accept    # le proxy
  ip saddr 127.0.0.1 tcp dport 2586 accept
  tcp dport 2586 drop
}

L’authentification de ntfy est bonne, mais un point d’entrée joignable depuis Internet reste un point d’entrée joignable depuis Internet. Si la seule chose qui doit l’atteindre est le proxy, dites-le au niveau des paquets.

Comptes, tokens et topics

ntfy user add --role=admin admin
ntfy user add publisher

# un token pour une machine qui ne fait que publier
ntfy token add --label=grafana publisher

# autoriser cet utilisateur à publier sur un seul topic, et rien d'autre
ntfy access publisher alerts write-only

Les autorisations par topic sont tout l’intérêt : le hook d’alerte Grafana reçoit un token qui peut publier vers alerts et rien d’autre. Si ce token fuit — et les tokens dans les fichiers de configuration finissent par fuiter — le rayon d’impact est « quelqu’un peut vous envoyer une notification », pas « quelqu’un peut lire chaque alerte que vous recevez ».

Publier

Publier est un POST HTTP, ce qui signifie que tout ce qui peut exécuter curl peut vous notifier. Sur un serveur ouvert, cela suffit ; avec deny-all, la requête a aussi besoin d’identifiants, comme dans l’exemple suivant :

curl -d "Disk on mon-srv is at 92%" https://ntfy.example.org/alerts

Avec un token et un peu de structure :

curl -H "Authorization: Bearer $TOKEN" \
     -H "Title: Disk pressure" \
     -H "Priority: high" \
     -H "Tags: warning,floppy_disk" \
     -d "mon-srv: / at 92% (5.1 GB free)" \
     https://ntfy.example.org/alerts

Priority règle l’insistance de la notification : default est une notification normale, high ajoute une longue vibration et une fenêtre surgissante, et urgent est pour ce qui ne peut pas attendre. Tags s’affichent comme une icône et une couleur dans l’application, ce qui vous permet de distinguer d’un coup d’œil un avertissement d’un message informatif sur un écran de verrouillage.

S’abonner, c’est la même URL sur une connexion longue durée — curl -s https://ntfy.example.org/alerts/json diffuse des lignes JSON, ce qui est pratique pour déboguer depuis un terminal sans l’application.

Ce que j’y branche réellement

  • Alertes Grafana — un contact point avec un token dédié. Chaque règle d’alerte atterrit dans un seul topic.
  • Notifications caméra — un petit service publie quand la détection d’objets se déclenche.
  • Événements du point d’accès WiFi — les arrivées et départs sur le réseau invité.
  • Sauvegardes et tâches cron — les tâches qui échouent en silence sont celles qui ont besoin de le dire.

Cette dernière catégorie est la vraie valeur. Les notifications ne portent pas principalement sur des graphiques de disque ; elles portent sur les tâches dont le mode de défaillance est le silence.

Pièges

  • Le modèle d’accès par défaut est ouvert. Réglez auth-default-access: deny-all avant que le service ne voie Internet, et accordez par topic.
  • enable-signup laissé actif laisse n’importe qui créer un compte. Désactivez-le.
  • Oublier behind-proxy transforme une limitation par client en limitation globale.
  • cache-duration: 24h signifie un historique court. Un client hors ligne pendant deux jours rate tout ce qui s’est passé entre-temps — le serveur garde 24 heures, pas « jusqu’à ce que vous le lisiez ». Si vous avez besoin d’un enregistrement durable, le pipeline syslog est l’enregistrement et le push est la piqûre de rappel.
  • Les pièces jointes expirent. Une notification avec une capture d’écran est un lien vers un fichier qui est supprimé après sa fenêtre d’expiration, sauf si le client l’a téléchargé.
  • Un canal de notification que vous ignorez est pire que pas de canal. ntfy rend facile l’ajout d’une règle par problème ; ajoutez-en peu, et faites en sorte que ce soient celles sur lesquelles vous agiriez à 03:00.

cd ~/blog