Auto-héberger ntfy pour les alertes push serveur
Déployez ntfy sur un VPS avec TLS et Docker Compose, protégez les topics par utilisateurs et ACL, puis envoyez des alertes depuis cron et systemd OnFailure.
Ce que fait un serveur ntfy auto-hébergé
Un serveur ntfy auto-hébergé transforme une requête HTTP POST en notification push sur votre téléphone. Vous publiez avec curl, puis le message arrive dans l’application Android, l’application iOS, un onglet de navigateur ou tout autre client capable de maintenir une connexion HTTP ouverte. Vous n’avez pas besoin d’installer de bibliothèque cliente ni d’exécuter de message broker.
ntfy adresse les messages par topic. Un topic est un nom placé dans le chemin de l’URL, comme https://ntfy.example.com/alerts, et il existe dès qu’un utilisateur y publie un message. Avec l’installation par défaut, toute personne qui connaît ce nom peut lire le topic et y publier des messages. C’est pourquoi la documentation du projet compare le nom d’un topic à un mot de passe. Ce modèle convient au service public ntfy.sh. Il ne convient pas à un serveur qui transporte les échecs de vos sauvegardes. Ce guide active donc l’authentification avant l’envoi du premier message.
Ce dont vous avez besoin avant de commencer
Vous avez besoin d’un VPS sous Ubuntu 24.04 ou Debian 13, avec Docker Engine et le plugin Compose, d’un nom de domaine et de très peu de RAM. Créez un enregistrement DNS (domain name system) de type A qui pointe ntfy.example.com vers l’adresse IP publique du serveur, puis vérifiez sa résolution avant toute autre opération.
dig +short ntfy.example.com
sudo ufw allow 80,443/tcp
sudo ufw statusdig doit afficher l’adresse IP de votre serveur. L’émission du certificat échoue si la commande n’affiche rien, car l’autorité de certification vérifie le nom depuis l’extérieur. Le port 80 reste ouvert, car ACME (automatic certificate management environment), le protocole utilisé par Let's Encrypt, l’emploie pour le challenge HTTP. Le conteneur ntfy n’expose lui-même aucun port public.
Écrire le fichier de configuration de ntfy
L’image Docker ne contient pas de fichier de configuration. Vous devez donc en créer un. Toutes les commandes suivantes de ce guide le lisent. Commencez par trouver l’ID utilisateur et l’ID de groupe sous lesquels le conteneur s’exécutera.
id -u
id -g
sudo install -d -o "$(id -u)" -g "$(id -g)" /etc/ntfy /var/cache/ntfy /var/lib/ntfy
sudo nano /etc/ntfy/server.ymlbase-url: "https://ntfy.example.com"
listen-http: ":2586"
behind-proxy: true
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "12h"
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"
enable-login: true
enable-signup: falseQuatre de ces lignes sont essentielles. base-url doit être exactement l’adresse HTTPS publique, car ntfy construit à partir de cette valeur les liens vers les pièces jointes et les requêtes de l’application web. Une valeur incorrecte produit une application web qui se charge, puis échoue pour chaque action. listen-http: ":2586" écoute sur toutes les interfaces du conteneur. Cela peut sembler imprudent, mais c’est correct : le conteneur possède son propre namespace réseau. Si vous le liez à 127.0.0.1, le port devient inaccessible depuis l’hôte et le port publié par Docker ne peut jamais s’y connecter. auth-default-access: "deny-all" définit toute la politique de sécurité, car il refuse les opérations de lecture et d’écriture sans autorisation explicite. behind-proxy: true indique à ntfy de récupérer l’adresse du client dans l’en-tête X-Forwarded-For. Les limites de débit comptent ainsi les visiteurs réels au lieu de considérer le reverse proxy comme un seul client très actif.
enable-login: true permet à l’application web et aux applications mobiles de se connecter avec un mot de passe. enable-signup reste à false, car permettre la création autonome de comptes sur un serveur privé revient à laisser une porte ouverte avec des étapes supplémentaires.
sudo chown "$(id -u):$(id -g)" /etc/ntfy/server.yml
sudo chmod 600 /etc/ntfy/server.ymlExécuter ntfy avec Docker Compose
Placez ceci dans /opt/ntfy/compose.yaml en remplaçant 1000:1000 par les deux nombres id -u et id -g affichés plus haut.
services:
ntfy:
image: binwiederhier/ntfy:v2.27.0
container_name: ntfy
command: serve
user: "1000:1000"
environment:
- TZ=UTC
volumes:
- /etc/ntfy:/etc/ntfy
- /var/cache/ntfy:/var/cache/ntfy
- /var/lib/ntfy:/var/lib/ntfy
ports:
- "127.0.0.1:2586:2586"
restart: unless-stoppedcd /opt/ntfy
sudo docker compose up -d
sudo docker compose logs ntfy
curl -s http://127.0.0.1:2586/v1/healthUn serveur sain répond à {"healthy":true}. Deux détails de ce fichier compose sont intentionnels. L’image est figée sur v2.27.0, la version actuelle en août 2026, plutôt que sur latest, car avec latest, le prochain docker compose pull modifie la version installée sur le serveur et vous ne le découvrez qu’ensuite dans le changelog. Le port est publié avec 127.0.0.1:2586:2586 : le conteneur est donc accessible uniquement depuis l’adresse loopback de l’hôte. Écrivez 2586:2586 à la place, et Docker insère ses propres règles de pare-feu avant les vôtres. Le port répond alors depuis Internet, même si ufw status indique qu’il est fermé. Ces deux habitudes s’appliquent aussi au prochain conteneur que vous ajouterez : un relais RustDesk auto-hébergé fige son tag d’image de la même manière, mais il ne peut pas se limiter à loopback, car ses ports de signalisation et de relais doivent répondre depuis Internet.
Si curl affiche Connection refused, consultez le log du conteneur. Une erreur de permission sur /var/lib/ntfy/user.db signifie que la ligne user: ne correspond pas au propriétaire de ces répertoires. Le processus ne peut donc pas créer sa propre base de données et s’arrête. Le guide sur les bases de Docker Compose pour un VPS explique plus en détail la gestion des propriétaires des volumes et les policies de redémarrage.
Placez TLS devant le service avec Caddy
Caddy demande et renouvelle lui-même le certificat. C’est le moyen le plus direct d’obtenir un TLS (transport layer security) fonctionnel.
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddyRemplacez le contenu de /etc/caddy/Caddyfile par trois lignes.
ntfy.example.com {
reverse_proxy 127.0.0.1:2586
}sudo systemctl reload caddy
curl -s https://ntfy.example.com/v1/healthLe même {"healthy":true} en HTTPS confirme que toute la chaîne fonctionne. Une 502 de Caddy signifie que ntfy n’est pas à l’écoute : vérifiez avec sudo ss -lntp | grep 2586. Une erreur de certificat signifie généralement que l’enregistrement DNS est incorrect ou que le port 80 est bloqué. sudo journalctl -u caddy -n 50 indique lequel des deux problèmes est présent. Pour ajouter un autre service plus tard, il suffit d’ajouter un bloc d’hôte dans le même Caddyfile. C’est ainsi qu’un service comme Halcyon, une interface de vidéoclub des années 90 pour votre bibliothèque Jellyfin peut être publié sur un deuxième sous-domaine du même serveur.
Si vous utilisez déjà nginx, reprenez les paramètres de proxy documentés par ntfy : proxy_http_version 1.1, proxy_buffering off, proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, ainsi que des délais d’expiration de lecture et d’envoi d’au moins trois minutes. Un abonné maintient une connexion HTTP ouverte pendant toute la durée de son écoute. Par défaut, nginx ferme une connexion upstream inactive après 60 secondes. Les abonnés se reconnectent donc en boucle et les messages envoyés pendant l’interruption sont perdus.
Créer des utilisateurs et restreindre l’accès aux topics
L’authentification est activée et personne n’a encore accès à quoi que ce soit, ce qui est le but recherché. Créez un compte administrateur pour vous-même et un compte machine pour les scripts. Ces commandes lisent /etc/ntfy/server.yml à l’intérieur du conteneur, d’où le montage du fichier de configuration comme volume.
sudo docker compose exec ntfy ntfy user add --role=admin admin
sudo docker compose exec ntfy ntfy user add robot
sudo docker compose exec ntfy ntfy user listChaque commande demande un mot de passe. Un administrateur ignore la liste de contrôle d’accès et peut lire et écrire sur tous les topics. Réservez donc ce compte à votre usage et à l’application mobile. robot est un utilisateur standard sans aucun accès tant que vous ne lui en accordez pas.
sudo docker compose exec ntfy ntfy access robot alerts write
sudo docker compose exec ntfy ntfy access robot "alerts_*" write
sudo docker compose exec ntfy ntfy accessUne ACL (liste de contrôle d’accès) associe un utilisateur, un topic et une permission. Le topic peut être un nom littéral ou un pattern dans lequel * correspond à n’importe quelle valeur. Ainsi, alerts_* couvre alerts_backup et alerts_db sans devoir exécuter une commande pour chaque hôte. La permission write signifie publier uniquement. Un token volé à un cron job ne peut donc pas s’abonner et relire ce qu’il a envoyé. Le nom d’utilisateur spécial everyone définit les actions autorisées pour un visiteur non authentifié. Utilisez-le uniquement pour rendre délibérément un élément public, comme ntfy access everyone status read.
Les scripts doivent utiliser un token, pas votre mot de passe.
sudo docker compose exec ntfy ntfy token add robotLa commande affiche un token commençant par tk_. Un token hérite exactement des accès de l’utilisateur auquel il appartient. Celui-ci peut donc publier sur les topics alerts, et rien d’autre. ntfy token list affiche les éléments existants, et ntfy token remove en révoque un sans modifier le mot de passe de l’utilisateur.
Envoyez votre premier message et vérifiez que le verrou fonctionne
Commencez par vérifier que la porte est fermée.
curl -s -o /dev/null -w '%{http_code}\n' -d "hello" https://ntfy.example.com/alertsCette commande affiche 403, et 403 est la réponse attendue : auth-default-access: "deny-all" refuse une publication anonyme. Envoyez maintenant un vrai message.
curl -H "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN" \
-H "Title: Nightly backup finished" \
-H "Priority: default" \
-H "Tags: white_check_mark" \
-d "42 GB copied in 11 minutes" \
https://ntfy.example.com/alertsLe serveur renvoie le message enregistré au format JSON. Vous savez ainsi qu’il a été accepté et non ignoré. Title correspond à la première ligne en gras. Priority va de 1 à 5, ou de min à urgent lorsqu’il est indiqué par son nom. Il détermine si le téléphone émet un son. Tags deviennent des emoji dans la notification lorsque le nom correspond à un short code d’emoji connu, et restent du texte brut dans le cas contraire.
Pour surveiller un topic depuis un terminal, diffusez son contenu en continu :
curl -s -u admin https://ntfy.example.com/alerts/rawcurl demande le mot de passe. Chaque message arrive sur une seule ligne. Les lignes vides qui apparaissent de temps en temps sont des keepalives. Ouvrir https://ntfy.example.com dans un navigateur et vous connecter avec le même compte vous donne accès à la version web du même flux.
Définir des limites de débit pour qu’un script ne puisse pas saturer le serveur
Par défaut, chaque visiteur dispose d’un compartiment de 60 requêtes, rechargé à raison d’une requête toutes les 5 secondes. Cette limite est généreuse pour un serveur privé, et un script bloqué dans une boucle de nouvelles tentatives l’épuise rapidement. Ajoutez des limites à server.yml.
visitor-request-limit-burst: 30
visitor-request-limit-replenish: "10s"
visitor-message-daily-limit: 500sudo docker compose restart ntfyUn visiteur qui dépasse la limite reçoit le code HTTP 429 au lieu d’un message distribué. La limite est comptabilisée par adresse du visiteur. C’est pourquoi behind-proxy: true est si important : sans lui, ntfy ne voit que l’adresse de Caddy, tous les clients sont considérés comme un seul visiteur, et un script trop bavard épuise le compartiment partagé par votre téléphone et vos autres serveurs.
Alerte en cas d’échec d’une tâche cron
Ne placez pas le token dans la ligne de commande. ps aux affiche la ligne de commande complète de chaque processus en cours à tous les utilisateurs du serveur. Un token transmis avec -H est donc lisible par n’importe quel compte local pendant toute la durée d’exécution de curl. Un fichier de configuration curl évite ce problème.
sudo install -d -m 700 /etc/ntfy-alert
printf 'header = "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN"\n' | sudo tee /etc/ntfy-alert/curlrc
sudo chmod 600 /etc/ntfy-alert/curlrcEncapsulez maintenant la tâche. Enregistrez ce contenu dans /usr/local/bin/backup-with-alert.sh, puis rendez-le exécutable avec chmod 750.
#!/bin/bash
out=$(/usr/local/bin/backup.sh 2>&1)
code=$?
if [ "$code" -ne 0 ]; then
printf '%s' "$out" | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
-H "Title: backup.sh failed with exit $code" \
-H "Priority: high" \
-H "Tags: warning" \
--data-binary @- \
https://ntfy.example.com/alerts
fi
exit "$code"17 3 * * * /usr/local/bin/backup-with-alert.sh >> /var/log/backup-alert.log 2>&1$? est capturé sur la ligne qui suit immédiatement la commande, car la commande suivante l’écraserait. La sortie passe par tail -c 1000, car ntfy impose une taille maximale aux messages et une notification ne remplace pas un outil de consultation des journaux. Le exit "$code" final conserve le code de retour d’origine. Tout autre outil qui surveille cette tâche continue donc à voir un échec. Testez l’ensemble en configurant le script pour utiliser /bin/false lors d’une exécution.
Une branche d’échec qui ne s’exécute jamais est pire que l’absence d’alertes, car elle donne l’impression que le silence indique une réussite. Cron fournit à votre tâche un environnement presque vide et un PATH bien plus court que celui de votre shell de connexion. Un script qui fonctionne lorsque vous le lancez manuellement peut donc s’arrêter avant même d’atteindre la ligne curl. Le guide expliquant pourquoi une tâche cron ne s’exécute pas traite ces problèmes d’environnement. Utilisez des chemins absolus partout et consultez le fichier journal après la première exécution planifiée au lieu de partir du principe que tout fonctionne.
Alerter en cas d’échec d’une unité systemd
Cron couvre les tâches planifiées. Les services qui s’exécutent en continu ont besoin de OnFailure=, que systemd exécute chaque fois qu’une unité passe à l’état failed. Créez une seule unité modèle et réutilisez-la pour chaque service du serveur. Enregistrez-la sous /etc/systemd/system/ntfy-unit-failed@.service.
[Unit]
Description=Send an ntfy alert because %i failed
[Service]
Type=oneshot
ExecStart=/usr/local/bin/ntfy-unit-failed %iPuis /usr/local/bin/ntfy-unit-failed, avec le mode 750 :
#!/bin/bash
unit="$1"
journalctl -u "$unit" -n 15 --no-pager -o cat | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
-H "Title: $unit failed on $(hostname -s)" \
-H "Priority: urgent" \
-H "Tags: rotating_light" \
--data-binary @- \
https://ntfy.example.com/alertsAssociez-la à un service avec un drop-in, afin qu’une mise à niveau du paquet ne puisse pas écraser votre modification.
sudo systemctl edit myapp.service[Unit]
OnFailure=ntfy-unit-failed@%n.service%n est remplacé par le nom complet de l’unité. L’instance devient donc ntfy-unit-failed@myapp.service, et %i, dans le modèle, transmet myapp.service au script comme premier argument. C’est ce qui permet à un seul modèle de servir pour toutes les unités. Vérifiez son fonctionnement avec une unité qui échoue volontairement, enregistrée sous /etc/systemd/system/ntfy-selftest.service.
[Unit]
Description=Deliberately failing unit
OnFailure=ntfy-unit-failed@%n.service
[Service]
Type=oneshot
ExecStart=/bin/falsesudo systemctl daemon-reload
sudo systemctl start ntfy-selftest.serviceLa commande de démarrage se termine avec un code différent de zéro et affiche Job for ntfy-selftest.service failed because the control process exited with error code. Le téléphone devrait vibrer environ une seconde plus tard. Supprimez ensuite l’unité de test.
Un piège mérite votre attention. OnFailure= s’exécute uniquement lorsqu’une unité atteint l’état failed. Un service avec Restart=always peut ne jamais l’atteindre, car systemd le redémarre à la place. L’unité n’échoue qu’après avoir dépassé StartLimitBurst redémarrages dans StartLimitIntervalSec. Définissez ces deux valeurs pour chaque service dont vous voulez surveiller les échecs. Sinon, une boucle de crash peut continuer silencieusement pendant plusieurs jours. Les timers remplacent plus proprement le modèle basé sur Cron présenté plus haut, car l’unité de service d’un timer reçoit OnFailure= automatiquement. Le guide des services systemd et des timers sur un VPS explique comment convertir l’un d’eux.
Configurer un moniteur de disponibilité sur le même topic
Uptime Kuma, le moniteur de statut auto-hébergé, propose un type de notification ntfy. Ouvrez Settings, puis Notifications, puis Setup Notification, choisissez Ntfy, définissez l’URL du serveur sur https://ntfy.example.com et le topic sur alerts, sélectionnez une priorité, puis collez le robot access token. Envoyez la notification de test avant d’enregistrer, car un nom de topic incorrect échoue silencieusement avec un grant write qui ne couvre pas ce topic.
La limite réelle de cette configuration est la suivante : un moniteur exécuté sur le même VPS ne peut pas vous informer que le VPS est indisponible, et ntfy ne peut pas transmettre la notification indiquant que ntfy est indisponible. Exécutez le moniteur sur une autre machine et configurez-lui un second canal de notification, par exemple l’e-mail, pour le moniteur qui surveille ntfy lui-même. Le type de moniteur Push d’Uptime Kuma couvre l’autre angle mort : votre tâche cron appelle une URL push après une exécution réussie, et Kuma vous alerte lorsque ces appels cessent d’arriver. Une branche d’échec ne se déclenche que lorsque la tâche s’exécute. Elle ne dit donc rien sur une tâche qui n’a jamais démarré.
Les instances ntfy auto-hébergées fonctionnent-elles sur Android et iPhone ?
Sur Android, oui, sans restriction. Installez l’application depuis Google Play ou F-Droid, ouvrez Settings, définissez le serveur par défaut sur https://ntfy.example.com, ajoutez votre compte dans l’écran de gestion des utilisateurs, puis abonnez-vous à alerts. La livraison instantanée maintient un foreground service actif afin que les messages arrivent même lorsque le téléphone est en mode doze. La notification permanente qui l’accompagne est une exigence d’Android pour les foreground services, et non un bug. La version F-Droid ne contient aucun code Firebase. Tous les abonnements utilisent donc la livraison instantanée. ntfy peut également servir de distributeur UnifiedPush, une solution open source qui remplace le service push de Google. Les autres applications compatibles avec UnifiedPush peuvent donc aussi envoyer leurs notifications via votre serveur.
Sur iOS, le fonctionnement dépend d’un composant que vous ne pouvez pas supprimer. Apple ne réveille une application en arrière-plan que par l’intermédiaire d’APNs (Apple push notification service). Seul le détenteur des identifiants de signature de l’application peut lui envoyer une notification. Votre serveur ne peut donc pas joindre directement l’application. ntfy résout ce problème avec un relay : votre serveur envoie à ntfy.sh un poll_request contenant l’ID du message. ntfy.sh le transmet ensuite via Firebase et APNs pour réveiller l’application. Celle-ci récupère alors le contenu du message sur votre serveur.
upstream-base-url: "https://ntfy.sh"Vous devez bien comprendre le coût de ce fonctionnement. Le contenu du message reste sur votre serveur, mais le fait qu’un message soit arrivé et son ID transitent par une infrastructure que vous n’administrez pas. Sans ce réglage, les notifications d’un serveur auto-hébergé arrivent en retard sur iPhone, ou n’arrivent pas du tout, car rien ne réveille l’application. Le seul moyen de supprimer le relay consiste à compiler et publier vous-même l’application iOS avec votre propre compte Apple Developer et vos propres clés APNs. Cela implique des frais annuels et une nouvelle compilation pour chaque mise à jour. Si ce relay ne convient pas à votre usage, utilisez Android ou l’application web de bureau pour les alertes.
Sauvegardes, mises à niveau et verrouillage de l’image
Deux chemins ne peuvent pas être régénérés : /etc/ntfy/server.yml et /var/lib/ntfy/user.db. Le second contient tous les utilisateurs, les hachages de mots de passe, les entrées ACL et les jetons. Traitez-le donc comme une clé privée.
sudo tar czf ntfy-backup.tgz -C / etc/ntfy var/lib/ntfy
sudo chmod 600 ntfy-backup.tgzCopiez ce fichier hors du serveur. cache.db contient uniquement les messages récents, soit 12 heures avec le cache-duration ci-dessus. Sa perte ne fait donc perdre aucune donnée importante à protéger. Pour effectuer une mise à niveau, modifiez le tag dans le fichier Compose, puis faites un pull.
sudo docker compose pull
sudo docker compose up -d
curl -s https://ntfy.example.com/v1/healthLisez d’abord les notes de version. Les bases de données SQLite sont migrées au démarrage. Revenir à un tag plus ancien après une modification du schéma n’est donc pas sûr. Conservez la sauvegarde que vous venez de créer jusqu’à ce que la nouvelle version ait fonctionné pendant une journée. Chaque service du serveur possède sa propre courte liste de chemins qui ne peuvent pas être régénérés. La comparaison entre PhotoPrism et Immich établit cette liste ainsi que les commandes de sauvegarde associées pour une photothèque hébergée sur le même type de VPS.
Gotify et Apprise
Gotify est l’option la plus légère : un seul binaire avec une interface web et une application Android, sans jokers pour les topics ni client iOS officiel. Il convient donc à un serveur privé dont la seule cible est Android. Apprise est une bibliothèque Python et un outil en ligne de commande, pas un serveur. Il diffuse un même message vers plus d’une centaine de services, dont ntfy. Il convient donc à un script qui doit envoyer une alerte à plusieurs endroits à la fois. ntfy est celui qui fournit un serveur, une API HTTP et des applications sur les deux plateformes mobiles. C’est pourquoi il constitue généralement le choix retenu pour les alertes envoyées depuis un serveur loué.
FAQ
Pourquoi la publication sur mon serveur ntfy renvoie-t-elle 403 ?
Avec auth-default-access: "deny-all" dans server.yml, une publication anonyme est refusée, conformément au comportement attendu. Envoyez des identifiants avec -u user:pass ou -H "Authorization: Bearer tk_...". Si vous envoyez déjà un token et obtenez toujours 403, l’utilisateur associé à ce token ne possède aucune entrée ACL correspondant au topic. Exécutez ntfy access pour afficher la liste complète. Notez qu’une autorisation write ne permet pas de s’abonner. Un compte qui peut publier sera donc quand même refusé lorsqu’il essaiera de lire le même topic.
Les notifications fonctionnent-elles sur iPhone avec un serveur ntfy auto-hébergé ?
Oui, mais elles passent par un relay auquel vous ne pouvez pas échapper. Apple réveille les applications uniquement via APNs (Apple push notification service), et seul l’éditeur de l’application peut y envoyer des notifications. ntfy transmet donc un poll_request contenant l’identifiant du message à ntfy.sh, qui le relaie ensuite vers l’appareil. Définissez upstream-base-url: "https://ntfy.sh" dans server.yml, puis redémarrez le conteneur. Le corps du message est toujours récupéré depuis votre serveur. Sans ce paramètre, les notifications iOS sont retardées ou n’apparaissent jamais.
Pourquoi l’alerte ntfy de ma tâche cron n’est-elle jamais arrivée ?
Exécutez d’abord la ligne curl seule pour vérifier que le token et le topic sont corrects. Si elle fonctionne manuellement, mais pas depuis cron, le problème se situe en amont de l’alerte : cron exécute les tâches avec un environnement minimal et un PATH court. Un script qui appelle une commande par son nom seul peut donc s’arrêter avant d’atteindre la ligne curl. Utilisez des chemins absolus, redirigez la sortie de la tâche vers un fichier journal, puis consultez ce fichier après l’exécution suivante. Une réponse 429 au lieu d’une livraison signifie que la limite de débit fonctionne et que votre script réessaie trop rapidement.
Dois-je exposer ntfy sur Internet public ?
Les applications mobiles doivent pouvoir y accéder depuis les réseaux mobiles. Un endpoint HTTPS public avec auth-default-access: "deny-all" et des ACL par topic constitue donc la configuration habituelle. Elle est sûre tant qu’aucun topic n’est lisible par everyone. Une instance accessible uniquement via VPN convient lorsque tous les abonnés sont des machines que vous contrôlez. Cette configuration convient mal aux téléphones, car l’application ne reçoit les messages que lorsque le tunnel est actif. Les alertes restent donc en file d’attente jusqu’à la reconnexion du téléphone.