Add config validation and dashboard
Add YAML config loading with validation, env overrides for secrets, and a web dashboard exposing health, stats, and recent events.
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
# ntfy-bridge — Architecture
|
||||
|
||||
## Philosophie
|
||||
|
||||
ntfy-bridge est un **daemon HTTP léger** écrit en V (~500 lignes) qui compile en un seul binaire natif statique. Il écoute des webhooks, se connecte au socket Docker, et poll des endpoints HTTP — puis transforme chaque événement en notification Ntfy formatée.
|
||||
|
||||
**Principes :**
|
||||
- **Un binaire, zéro runtime** — pas de Node, Python, JVM ou conteneur obligatoire
|
||||
- **Config-driven** — tout passe par le fichier YAML, pas de recompilation
|
||||
- **Fail-safe** — un échec réseau vers Ntfy ne crashe pas le daemon
|
||||
- **Silencieux par défaut** — ne spamme pas, utilise les bons niveaux de priorité Ntfy (1-5)
|
||||
- **Extensible** — ajouter une source = implémenter un module dans `sources/`
|
||||
|
||||
## Architecture globale
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ntfy-bridge │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
|
||||
│ │ HTTP │ │ Docker │ │ HTTP │ │ Cron │ │
|
||||
│ │ Server │ │ Watcher │ │ Poller │ │ Receiver │ │
|
||||
│ │ :9090 │ │ goroutine│ │ goroutine│ │ /webhooks │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬──────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────────┼──────────────┼──────────────┘ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────────────┐ │
|
||||
│ │ Event Pipeline │ │
|
||||
│ │ ┌────────┐ ┌────────┐ │ │
|
||||
│ │ │Parse & │ │Dedup & │ │ │
|
||||
│ │ │Format │──│RateLim │ │ │
|
||||
│ │ └────────┘ └────────┘ │ │
|
||||
│ └────────────┬─────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────┐ │
|
||||
│ │ Ntfy Publisher │ │
|
||||
│ │ POST /<topic> │ │
|
||||
│ └──────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Flux de données
|
||||
|
||||
### 1. Webhook entrant (Gitea, Uptime Kuma, generic)
|
||||
```
|
||||
POST /webhooks/gitea-flowdeck
|
||||
│
|
||||
▼
|
||||
1. Verify signature (optionnel)
|
||||
2. Parse JSON → Event struct
|
||||
3. Route vers le transformer approprié
|
||||
4. Appliquer priority_map
|
||||
5. Appliquer template de message
|
||||
6. POST vers Ntfy
|
||||
```
|
||||
|
||||
### 2. Docker watcher (socket)
|
||||
```
|
||||
goroutine DockerWatcher
|
||||
│
|
||||
▼
|
||||
1. Connexion au socket Docker (/var/run/docker.sock)
|
||||
2. Stream events via GET /events?filters=...
|
||||
3. Filtrer par événements configurés (die, oom, health_status)
|
||||
4. Extraire container_name, image, exit_code
|
||||
5. Appliquer template
|
||||
6. POST vers Ntfy
|
||||
```
|
||||
|
||||
### 3. HTTP Poller
|
||||
```
|
||||
goroutine HttpPoller (toutes les N secondes)
|
||||
│
|
||||
▼
|
||||
1. GET <url> avec timeout configuré
|
||||
2. Si status ≠ expected → Event(priority=5)
|
||||
3. Si OK et précédemment DOWN → Event(priority=1, tags="white_check_mark")
|
||||
4. Sinon → rien (pas de notification si tout va bien)
|
||||
```
|
||||
|
||||
### 4. Cron receiver
|
||||
```
|
||||
POST /webhooks/cron-disk
|
||||
│
|
||||
▼
|
||||
1. Body = texte brut du script cron
|
||||
2. Pass-through vers Ntfy
|
||||
3. Le script cron contrôle son propre format
|
||||
```
|
||||
|
||||
## Modèle de données
|
||||
|
||||
```v
|
||||
struct Config { // dans config.v
|
||||
server ServerConfig
|
||||
defaults DefaultConfig
|
||||
sources SourcesConfig
|
||||
}
|
||||
|
||||
struct ServerConfig {
|
||||
url string // URL du serveur Ntfy
|
||||
auth_token string // Token d'auth (optionnel)
|
||||
listen string // Adresse d'écoute HTTP (:9090)
|
||||
}
|
||||
|
||||
struct DefaultConfig {
|
||||
priority int // 1-5
|
||||
tags []string // ["loudspeaker"]
|
||||
}
|
||||
|
||||
struct Source { // types spécifiques dans sources/event.v
|
||||
name string
|
||||
webhook_path string
|
||||
topic string
|
||||
template string // Go-like template
|
||||
priority_map map[string]int
|
||||
tags []string
|
||||
}
|
||||
|
||||
struct Event { // dans sources/event.v
|
||||
source string // "gitea", "docker", "uptime_kuma", "http_poll", "cron"
|
||||
name string // nom de la source configurée
|
||||
topic string // topic Ntfy cible
|
||||
priority int // 1-5
|
||||
tags []string
|
||||
message string // message formaté final
|
||||
raw string // payload brut (pour debug)
|
||||
}
|
||||
```
|
||||
|
||||
## Pipeline de transformation
|
||||
|
||||
Chaque source implémente l'interface :
|
||||
|
||||
```v
|
||||
interface Transformer {
|
||||
transform(raw string, source &Source) ?Event
|
||||
}
|
||||
```
|
||||
|
||||
### Transformers inclus
|
||||
|
||||
| Transformer | Entrée | Sortie |
|
||||
|---|---|---|
|
||||
| `gitea_transformer` | JSON webhook Gitea | `🔨 [FlowDeck] bruno pushed to main: "Fix bug" (a3f2c1d)` |
|
||||
| `uptime_kuma_transformer` | JSON webhook Kuma | `🚨 Gitea is DOWN — 503 — since 14:32` |
|
||||
| `docker_transformer` | Docker event JSON | `🐳 flowdeck exited OOMKilled on docker-prod-1` |
|
||||
| `http_poll_transformer` | HTTP response | `❌ obsigate.dracodev.net/health → timeout 30s` |
|
||||
| `generic_transformer` | Raw body | Pass-through, pas de transformation |
|
||||
|
||||
### Priorités Ntfy
|
||||
|
||||
| Niveau | Usage | Exemple |
|
||||
|---|---|---|
|
||||
| 5 (urgent) | Service critique down, container OOM | Uptime Kuma DOWN |
|
||||
| 4 (high) | PR ouverte, container crash | Gitea pull_request, Docker die |
|
||||
| 3 (default) | Push, issue, activité normale | Gitea push |
|
||||
| 2 (low) | Info, succès | Service back UP |
|
||||
| 1 (min) | Debug, heartbeat | Health check OK (si configuré) |
|
||||
|
||||
## Déduplication et rate limiting
|
||||
|
||||
- **Déduplication** : même source + même type d'événement + même cible → cooldown 5 minutes
|
||||
- **Rate limiting** : max 10 notifs/minute/topic (configurable)
|
||||
- **Uptime Kuma spécifique** : les "down" répétés dans un intervalle de 2 min sont dédupliqués
|
||||
|
||||
## Structure du projet
|
||||
|
||||
```
|
||||
ntfy-bridge/
|
||||
├── README.md # Vue d'ensemble, quickstart
|
||||
├── ARCHITECTURE.md # Ce document
|
||||
├── ROADMAP.md # Phases de développement
|
||||
├── CONTRIBUTING.md # Guide de contribution
|
||||
├── ntfy-bridge.example.yaml # Exemple de configuration complet
|
||||
├── main.v # Entrypoint, parsing CLI
|
||||
├── config.v # Chargement + validation YAML
|
||||
├── server.v # HTTP server + routing webhooks
|
||||
├── ntfy.v # Client HTTP Ntfy (POST)
|
||||
├── dedup.v # Déduplication + rate limiting
|
||||
├── template.v # Mini moteur de template
|
||||
├── log.v # Logging structuré
|
||||
├── docker_watcher.v # Watcher socket Docker (Unix)
|
||||
├── sources/ # Types Event + transformers
|
||||
│ ├── event.v # Types Event, Source
|
||||
│ ├── gitea.v # Transformer Gitea
|
||||
│ ├── uptime_kuma.v # Transformer Uptime Kuma
|
||||
│ ├── docker.v # Transformer Docker events
|
||||
│ ├── http_poll.v # Transformer HTTP poll
|
||||
│ ├── generic.v # Webhook passe-partout
|
||||
│ └── cron.v # Webhook cron
|
||||
├── *_test.v # Tests unitaires
|
||||
├── scripts/
|
||||
│ └── example-cron-disk.sh # Exemple script cron → Ntfy
|
||||
└── v.mod # Dépendances V
|
||||
```
|
||||
|
||||
## Dépendances V (v.mod)
|
||||
|
||||
```v
|
||||
Module {
|
||||
name: 'ntfy-bridge'
|
||||
description: 'Homelab notification hub — aggregates Gitea, Docker, Uptime Kuma → Ntfy'
|
||||
version: '0.1.0'
|
||||
deps: [
|
||||
'ui-driver.cua'
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Dépendances externes minimales :
|
||||
- `vsl` — parsing YAML (sinon implémenter un parseur minimal)
|
||||
- `x.net` — client HTTP (ou lib standard V `net`)
|
||||
- `json` — stdlib V pour le parsing JSON
|
||||
|
||||
En réalité, V a tout dans sa stdlib : `net.http`, `json`, `time`, `os`, `flag`. Le projet vise **zéro dépendance externe**.
|
||||
|
||||
## Déploiement
|
||||
|
||||
### Option A : Binaire nu + systemd
|
||||
```ini
|
||||
# /etc/systemd/system/ntfy-bridge.service
|
||||
[Unit]
|
||||
Description=ntfy-bridge notification hub
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/ntfy-bridge --config /etc/ntfy-bridge.yaml
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
### Option B : Conteneur Docker
|
||||
```dockerfile
|
||||
FROM alpine:latest
|
||||
COPY ntfy-bridge /usr/local/bin/
|
||||
COPY ntfy-bridge.yaml /etc/
|
||||
EXPOSE 9090
|
||||
CMD ["/usr/local/bin/ntfy-bridge", "--config", "/etc/ntfy-bridge.yaml"]
|
||||
```
|
||||
|
||||
### Option C : Compilation croisée
|
||||
```bash
|
||||
v -os windows . -o ntfy-bridge.exe # Pour Windows
|
||||
v -os linux . -o ntfy-bridge # Pour Linux
|
||||
v -os macos . -o ntfy-bridge-mac # Pour macOS
|
||||
```
|
||||
|
||||
## Sécurité
|
||||
|
||||
- **Signature webhooks** : vérification HMAC-SHA256 optionnelle pour Gitea
|
||||
- **Auth token** : token optionnel pour le serveur Ntfy (si auth activée)
|
||||
- **Pas d'exposition externe** : le serveur HTTP écoute sur localhost par défaut (:9090)
|
||||
- **Rate limiting interne** : max 10 notifs/minute/source pour éviter le spam
|
||||
- **Input validation** : tout JSON entrant est validé avant processing
|
||||
- **No secrets in config** : le token Ntfy peut être passé via variable d'environnement `NTFY_TOKEN`
|
||||
|
||||
## Métriques et observabilité
|
||||
|
||||
- **Health endpoint** : `GET /health` → 200 OK + uptime + compteur de notifs
|
||||
- **Stats endpoint** : `GET /stats` → compteurs par source, erreurs, latence Ntfy
|
||||
- **Logging** : stdout en JSON structuré (timestamp, level, source, event, error)
|
||||
@@ -0,0 +1,94 @@
|
||||
# Contributing to ntfy-bridge
|
||||
|
||||
## Stack
|
||||
|
||||
- **Langage** : [V](https://vlang.io/) — compilé, rapide, syntaxe proche de Go
|
||||
- **Dépendances** : Zéro dépendance externe (stdlib V uniquement)
|
||||
- **Build** : `v .` → binaire natif statique
|
||||
|
||||
## Setup développement
|
||||
|
||||
```bash
|
||||
# Installer V
|
||||
curl -s https://github.com/vlang/v/releases/latest/download/v_linux.zip -o /tmp/v.zip
|
||||
unzip /tmp/v.zip -d /tmp && sudo /tmp/v/v symlink
|
||||
|
||||
# Cloner
|
||||
git clone https://git.dracodev.net/bruno/ntfy-bridge.git
|
||||
cd ntfy-bridge
|
||||
|
||||
# Compiler (mode dev avec hot reload)
|
||||
v watch run .
|
||||
|
||||
# Tests
|
||||
v test .
|
||||
|
||||
# Build production
|
||||
v -prod .
|
||||
```
|
||||
|
||||
## Structure du code
|
||||
|
||||
```
|
||||
.
|
||||
├── main.v # Entrypoint, flag parsing, orchestration
|
||||
├── config.v # Config loading + validation
|
||||
├── server.v # HTTP server, webhook routing
|
||||
├── ntfy.v # Ntfy HTTP client
|
||||
├── dedup.v # Deduplication + rate limiting
|
||||
├── template.v # Mini template engine
|
||||
├── log.v # Structured logging
|
||||
├── docker_watcher.v # Docker socket watcher (Unix)
|
||||
├── sources/ # Event types + source-specific transformers
|
||||
│ ├── event.v
|
||||
│ ├── gitea.v
|
||||
│ ├── uptime_kuma.v
|
||||
│ ├── docker.v
|
||||
│ ├── http_poll.v
|
||||
│ ├── generic.v
|
||||
│ └── cron.v
|
||||
└── *_test.v # Unit tests
|
||||
```
|
||||
|
||||
## Ajouter une nouvelle source
|
||||
|
||||
1. Créer `sources/ma_source.v`
|
||||
2. Implémenter la fonction `transform(raw string, source MaSource) ?Event`
|
||||
3. Déclarer le type source dans `sources/event.v`
|
||||
4. Référencer le type dans `config.v` (`SourcesConfig`)
|
||||
5. Router l'endpoint dans `server.v`
|
||||
6. Ajouter un test dans `ma_source_test.v`
|
||||
|
||||
## Conventions de code
|
||||
|
||||
- **Nommage** : snake_case pour les fonctions/variables, PascalCase pour les structs
|
||||
- **Gestion d'erreurs** : utiliser le type `?` (Option/Result) de V
|
||||
- **Logging** : `log.info()`, `log.warn()`, `log.error()` avec contexte
|
||||
- **Messages de commit** : [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
- `feat: add Gitea webhook transformer`
|
||||
- `fix: handle Docker socket disconnect`
|
||||
- `docs: update ARCHITECTURE.md`
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
# Tous les tests
|
||||
v test .
|
||||
|
||||
# Test spécifique
|
||||
v test gitea_test.v
|
||||
|
||||
# Avec verbose
|
||||
v test . -stats
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
Le repo utilise Gitea Actions. Le workflow dans `.gitea/workflows/ci.yml` :
|
||||
- Compile en mode `-prod`
|
||||
- Lance `v test .`
|
||||
- Vérifie le formatting (`v fmt -verify`)
|
||||
|
||||
## Questions ?
|
||||
|
||||
Ouvrir une issue sur https://git.dracodev.net/bruno/ntfy-bridge/issues
|
||||
@@ -0,0 +1,95 @@
|
||||
# ntfy-bridge — Roadmap
|
||||
|
||||
## Phase 1 : MVP (core engine) — v0.1.0
|
||||
|
||||
Objectif : daemon qui compile, lit une config, écoute des webhooks et envoie vers Ntfy.
|
||||
|
||||
- [ ] `main.v` — CLI args (`--config`, `--version`, `--validate`)
|
||||
- [ ] `config.v` — Chargement + validation du YAML
|
||||
- [ ] `server.v` — HTTP server sur `:9090` avec routing basique
|
||||
- [ ] `event.v` — Types de données : `Event`, `Config`, `Source`
|
||||
- [ ] `ntfy.v` — Client HTTP POST vers Ntfy (topic, message, priority, tags)
|
||||
- [ ] `sources/generic.v` — Webhook passe-partout (POST raw → Ntfy)
|
||||
- [ ] `log.v` — Logging structuré (timestamp, level, message)
|
||||
- [ ] `ntfy-bridge.example.yaml` — Config d'exemple complète et commentée
|
||||
|
||||
**Sortie** : `ntfy-bridge` compile, accepte un webhook générique et l'envoie vers Ntfy.
|
||||
|
||||
## Phase 2 : Sources spécialisées — v0.2.0
|
||||
|
||||
- [ ] `sources/gitea.v` — Transformer Gitea (push, PR, issues, releases)
|
||||
- Parse le JSON webhook Gitea
|
||||
- Format : `🔨 [repo] auteur action: "message" (sha)`
|
||||
- Priority map par type d'événement
|
||||
- [ ] `sources/uptime_kuma.v` — Transformer Uptime Kuma
|
||||
- Parse le JSON webhook Kuma (heartbeat)
|
||||
- Format : `🚨 monitor is DOWN — status — since time`
|
||||
- Priority 5 pour DOWN, 1 pour UP
|
||||
- [ ] `sources/docker.v` — Watcher socket Docker
|
||||
- Connexion au socket Docker (local + distant TCP)
|
||||
- Filtrage par événements (die, health_status, oom)
|
||||
- Template de message configurable
|
||||
- Multi-hôtes (plusieurs sockets dans la config)
|
||||
- [ ] `sources/http_poll.v` — Poller HTTP
|
||||
- Goroutine de polling périodique (intervalle configurable)
|
||||
- Vérification status code + timeout
|
||||
- State machine up/down avec notification uniquement au changement
|
||||
- [ ] `dedup.v` — Déduplication basique
|
||||
- Cache LRU avec TTL (5 min par défaut)
|
||||
- Clé de déduplication : source + type + cible
|
||||
|
||||
**Sortie** : Toutes les sources majeures sont intégrées et fonctionnelles.
|
||||
|
||||
## Phase 3 : Robustesse — v0.3.0
|
||||
|
||||
- [ ] `dedup.v` amélioré — Rate limiting global par topic
|
||||
- [ ] Signature webhooks — Vérification HMAC-SHA256 optionnelle (Gitea)
|
||||
- [ ] Retry logic — Retry avec backoff exponentiel vers Ntfy (3 tentatives)
|
||||
- [ ] Graceful shutdown — SIGTERM → drain des événements en cours
|
||||
- [ ] Health endpoint — `GET /health` → 200 + uptime + stats basiques
|
||||
- [ ] Stats endpoint — `GET /stats` → compteurs par source
|
||||
- [ ] Config reload — `SIGHUP` → reload config sans redémarrage
|
||||
- [ ] Tests unitaires — `config_test.v`, `gitea_test.v`, `dedup_test.v`
|
||||
|
||||
**Sortie** : Le daemon est prêt pour la production homelab.
|
||||
|
||||
## Phase 4 : Qualité de vie — v0.4.0
|
||||
|
||||
- [ ] Template engine avancé — Support des variables dans les messages
|
||||
```
|
||||
"🐳 {container_name} → {status} (exit: {exit_code}) on {host}"
|
||||
```
|
||||
- [ ] Silence rules — `POST /api/silence?duration=30m` mute temporaire
|
||||
- [ ] Grouping — Regrouper N notifications similaires en une seule
|
||||
- [ ] Webhook secret validation — HMAC pour tous les webhooks
|
||||
- [ ] Docker Compose example — `docker-compose.yml` prêt à l'emploi
|
||||
- [ ] systemd unit file — `ntfy-bridge.service`
|
||||
- [ ] CI/CD via Gitea Actions — build + test automatique
|
||||
|
||||
**Sortie** : Expérience utilisateur complète et agréable.
|
||||
|
||||
## Phase 5 : Futures idées — v0.5.0+
|
||||
|
||||
- [ ] Web UI minimale — Page de statut des sources + historique récent
|
||||
- [ ] Filtres avancés — Expressions conditionnelles par source
|
||||
```yaml
|
||||
filters:
|
||||
- match: { container_name: "test-*" }
|
||||
action: drop
|
||||
```
|
||||
- [ ] Notifications structurées — Support des actions Ntfy (boutons click)
|
||||
- [ ] Intégration Prometheus — Métriques exposées au format OpenMetrics
|
||||
- [ ] Webhook sortant — Forwarder les événements vers un autre webhook (Slack, Discord)
|
||||
- [ ] Support multi-utilisateurs — ACLs par webhook_path
|
||||
- [ ] Fichier d'état — Persistance de l'état up/down des health checks
|
||||
- [ ] Plugin system — Sources customisables via dll/.so (futur lointain)
|
||||
|
||||
## Suivi des versions
|
||||
|
||||
| Version | Date cible | Contenu |
|
||||
|---------|-----------|---------|
|
||||
| v0.1.0 | — | Moteur core + webhook générique |
|
||||
| v0.2.0 | — | Sources Gitea, Uptime Kuma, Docker, HTTP poll |
|
||||
| v0.3.0 | — | Robustesse, tests, health check, rate limiting |
|
||||
| v0.4.0 | — | Templates, silence rules, grouping, CI/CD |
|
||||
| v0.5.0+ | — | Web UI, Prometheus, plugins |
|
||||
@@ -0,0 +1,255 @@
|
||||
# Configurer les webhooks Gitea avec ntfy-bridge
|
||||
|
||||
Guide tape par tape pour connecter Gitea ntfy-bridge et recevoir des notifications Ntfy pour chaque push, PR, issue ou release.
|
||||
|
||||
---
|
||||
|
||||
## Prrequis
|
||||
|
||||
- **ntfy-bridge** install et configur (voir [README.md](../README.md))
|
||||
- Un serveur **Ntfy** accessible (ex: `https://ntfy.dracodev.net`)
|
||||
- Un compte **Gitea** avec accs admin au repo (ex: `https://git.dracodev.net`)
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Gitea (git.dracodev.net) ntfy-bridge (ton serveur) Ntfy (ntfy.dracodev.net)
|
||||
┌─────────────────────┐ ┌────────────────────────┐ ┌──────────────────────┐
|
||||
│ bruno/flowdeck │ │ coute sur :9090 │ │ Topic: dev-notifs │
|
||||
│ │ POST │ │ POST │ │
|
||||
│ vnement (push) │──────────→│ /webhooks/gitea-... │───────→│ Ton tlphone │
|
||||
│ JSON + HMAC sig │ │ │ │ │
|
||||
│ │ │ Parse, format, forward │ │ │
|
||||
└─────────────────────┘ └────────────────────────┘ └──────────────────────┘
|
||||
```
|
||||
|
||||
**Le principe** : Gitea envoie un POST HTTP contenant un JSON avec tous les dtails de l'vnement. ntfy-bridge l'coute, le parse, le formate, et le forward vers Ntfy.
|
||||
|
||||
---
|
||||
|
||||
## tape 1 — Configurer ntfy-bridge
|
||||
|
||||
### 1a. Modifier `ntfy-bridge.yaml`
|
||||
|
||||
```yaml
|
||||
server:
|
||||
url: https://ntfy.dracodev.net # Ton serveur Ntfy
|
||||
listen: "0.0.0.0:9090" # couter sur le rseau (pas juste localhost)
|
||||
hmac_secret: "un-secret-que-tu-choisis" # Secret partag avec Gitea
|
||||
|
||||
sources:
|
||||
gitea:
|
||||
- name: "FlowDeck activity" # Nom affich dans les logs/dashboard
|
||||
webhook_path: /webhooks/gitea-flowdeck # Chemin d'coute
|
||||
repo: bruno/flowdeck # Repo concern
|
||||
topic: dev-notifs # Topic Ntfy cible
|
||||
priority_map: # Priorits par type d'vent
|
||||
pull_request: 4 # 4 = high
|
||||
issue: 3 # 3 = default
|
||||
push: 2 # 2 = low
|
||||
template: | # Format du message (optionnel)
|
||||
{user} {action} sur **[{repo}]**: "{title}"
|
||||
```
|
||||
|
||||
**Points cls** :
|
||||
- `listen: "0.0.0.0:9090"` — indispensable si Gitea est sur un autre serveur. `127.0.0.1` = localhost seulement.
|
||||
- `hmac_secret` — le mme secret que tu mettras dans Gitea. Optionnel mais recommand.
|
||||
- `webhook_path` — le chemin dans l'URL. Doit tre unique par source.
|
||||
- `template` — si absent, un format par dfaut est gnr automatiquement avec emoji.
|
||||
|
||||
### 1b. Lancer ntfy-bridge
|
||||
|
||||
```bash
|
||||
cd /c/dev/git/V/ntfy-bridge
|
||||
./ntfy-bridge.exe --config ntfy-bridge.yaml
|
||||
```
|
||||
|
||||
Sortie attendue :
|
||||
|
||||
```
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
ntfy-bridge v0.1.0 — Homelab Notification Hub
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
Ntfy server: https://ntfy.dracodev.net
|
||||
Listening on: http://0.0.0.0:9090
|
||||
Dashboard: http://0.0.0.0:9090/
|
||||
|
||||
Sources loaded:
|
||||
Gitea: 2 webhooks
|
||||
Uptime Kuma: 1 webhooks
|
||||
Docker: 1 watchers
|
||||
HTTP Poll: 1 pollers (5 checks)
|
||||
Cron: 2 webhooks
|
||||
Generic: 1 webhooks
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
### 1c. Vrifier que a marche
|
||||
|
||||
```bash
|
||||
# Test health endpoint
|
||||
curl http://localhost:9090/health
|
||||
# → {"status":"ok","uptime_seconds":12,"total_notifications":0}
|
||||
|
||||
# Test dashboard
|
||||
curl http://localhost:9090/
|
||||
# → HTML du dashboard
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## tape 2 — Configurer Gitea
|
||||
|
||||
### 2a. Aller dans les rglages du repo
|
||||
|
||||
1. Ouvre `https://git.dracodev.net/bruno/flowdeck`
|
||||
2. Clic sur l'engrenage **Settings** (haut droite)
|
||||
3. Menu gauche : **Webhooks**
|
||||
4. Bouton **Add Webhook** → choisir **Gitea**
|
||||
|
||||
### 2b. Remplir le formulaire
|
||||
|
||||
| Champ | Valeur | Notes |
|
||||
|---|---|---|
|
||||
| **Target URL** | `http://192.168.30.X:9090/webhooks/gitea-flowdeck` | Remplacer X par l'IP relle du serveur |
|
||||
| **HTTP Method** | POST | |
|
||||
| **POST Content Type** | application/json | |
|
||||
| **Secret** | `un-secret-que-tu-choisis` | Identique `hmac_secret` dans le YAML |
|
||||
| **Trigger On** | Slectionner les vnements souhauts | Push, Pull Request, Issue, Release... |
|
||||
|
||||
**Trouver la bonne IP** : sur le serveur o tourne ntfy-bridge :
|
||||
|
||||
```bash
|
||||
# Linux
|
||||
ip addr show | grep "inet " | grep -v 127.0.0.1
|
||||
|
||||
# Windows
|
||||
ipconfig | findstr "IPv4"
|
||||
```
|
||||
|
||||
### 2c. Cliquer "Add Webhook"
|
||||
|
||||
Gitea envoie immdiatement un **test ping** pour vrifier la connectivit.
|
||||
|
||||
Rsultat russi :
|
||||
|
||||
```
|
||||
✓ Delivery successful (HTTP 200)
|
||||
```
|
||||
|
||||
En cas d'chec :
|
||||
|
||||
| Erreur | Cause probable | Solution |
|
||||
|---|---|---|
|
||||
| Connection refused | ntfy-bridge n'est pas lanc | Lancer `./ntfy-bridge.exe` |
|
||||
| Connection refused | Firewall bloque le port 9090 | Ouvrir le port dans le firewall |
|
||||
| HTTP 404 | Mauvais `webhook_path` | Vrifier que `/webhooks/gitea-flowdeck` est exact |
|
||||
| HTTP 401 | Mauvais `hmac_secret` | Vrifier que le secret est identique des deux cts |
|
||||
| Timeout | Mauvaise IP ou rseau inaccessible | Vrifier la connectivit rseau |
|
||||
|
||||
---
|
||||
|
||||
## tape 3 — Tester avec un vrai vnement
|
||||
|
||||
### Option A : Test simul (curl)
|
||||
|
||||
Depuis n'importe quel poste :
|
||||
|
||||
```bash
|
||||
curl -X POST http://192.168.30.X:9090/webhooks/gitea-flowdeck \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Hub-Signature-256: sha256=..." \
|
||||
-d '{
|
||||
"commits": [{"id": "abc1234567890abcdef1234567890abcdef1234", "message": "test notification ntfy-bridge"}],
|
||||
"pusher": {"username": "bruno"},
|
||||
"repository": {"full_name": "bruno/flowdeck"}
|
||||
}'
|
||||
```
|
||||
|
||||
> Note : si `hmac_secret` est configur, gnre la signature correcte ou dsactive-le temporairement pour le test.
|
||||
|
||||
### Option B : Test rel
|
||||
|
||||
Fais un push, cre une PR, ou ouvre une issue dans le repo Gitea. Tu devrais recevoir une notification Ntfy dans les secondes qui suivent.
|
||||
|
||||
Exemple de notification reue :
|
||||
|
||||
```
|
||||
bruno pushed sur [bruno/flowdeck]: "fix: corrige le bug du dashboard"
|
||||
```
|
||||
|
||||
Ou avec le template par dfaut :
|
||||
|
||||
```
|
||||
[bruno/flowdeck] bruno pushed: "fix: corrige le bug du dashboard" (abc1234)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ajouter d'autres repos
|
||||
|
||||
Rpte les mmes tapes pour chaque repo :
|
||||
|
||||
### Dans `ntfy-bridge.yaml`
|
||||
|
||||
```yaml
|
||||
sources:
|
||||
gitea:
|
||||
- name: "FlowDeck activity"
|
||||
webhook_path: /webhooks/gitea-flowdeck
|
||||
repo: bruno/flowdeck
|
||||
topic: dev-notifs
|
||||
|
||||
- name: "ObsiGate activity"
|
||||
webhook_path: /webhooks/gitea-obsigate
|
||||
repo: bruno/obsigate
|
||||
topic: dev-notifs
|
||||
|
||||
- name: "Imago activity"
|
||||
webhook_path: /webhooks/gitea-imago
|
||||
repo: bruno/imago
|
||||
topic: dev-notifs
|
||||
```
|
||||
|
||||
### Dans Gitea
|
||||
|
||||
Pour chaque repo : Settings → Webhooks → Add Webhook avec l'URL correspondante.
|
||||
|
||||
```text
|
||||
http://192.168.30.X:9090/webhooks/gitea-flowdeck → repo bruno/flowdeck
|
||||
http://192.168.30.X:9090/webhooks/gitea-obsigate → repo bruno/obsigate
|
||||
http://192.168.30.X:9090/webhooks/gitea-imago → repo bruno/imago
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dpannage rapide
|
||||
|
||||
```bash
|
||||
# Vrifier que ntfy-bridge tourne
|
||||
curl http://localhost:9090/health
|
||||
|
||||
# Voir les stats
|
||||
curl http://localhost:9090/stats
|
||||
|
||||
# Voir la config (sans les secrets)
|
||||
curl http://localhost:9090/api/config
|
||||
|
||||
# Voir l'historique des derniers vnements
|
||||
curl http://localhost:9090/api/history
|
||||
|
||||
# Voir le dashboard web
|
||||
# Ouvre http://localhost:9090/ dans ton navigateur
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rfrences
|
||||
|
||||
- [README.md](../README.md) — Vue d'ensemble du projet
|
||||
- [ARCHITECTURE.md](../ARCHITECTURE.md) — Architecture dtaille
|
||||
- [ntfy-bridge.example.yaml](../ntfy-bridge.example.yaml) — Exemple de config complet
|
||||
- [Documentation webhooks Gitea](https://docs.gitea.com/usage/webhooks)
|
||||
- [Documentation Ntfy](https://docs.ntfy.sh/)
|
||||
Reference in New Issue
Block a user