Veille : mon agrégateur RSS auto-hébergé
Sommaire
Pendant des années, ma veille techno tenait dans une page HTML et deux scripts PHP sur un hébergement mutualisé. Chaque navigateur retéléchargeait lui-même la quarantaine de flux toutes les 30 minutes, la liste était codée en dur et rien n'était conservé au-delà de la veille. Veille la remplace : un agrégateur RSS/Atom auto-hébergé, multi-comptes, qui tient dans un conteneur Docker.
Le code est sur GitHub : github.com/xaviergregor/veille.


Ce que fait Veille
La lecture
- Articles groupés par jour (Hier / Aujourd'hui), sur une période au choix : aujourd'hui, hier + aujourd'hui, 7 jours ou 30 jours.
- Filtres par catégorie, puis par source : un clic sur le nom d'un site dans une carte n'affiche plus que ses articles.
- Recherche dans les titres et les sources, accessible avec la touche
/. - Marquer lu article par article, ou tout marquer lu sur ce qui est affiché, avec un bouton Annuler. Les articles lus restent consultables.
- Synchronisation entre appareils : l'état lu / non lu suit le compte. Hors connexion, les actions sont mises en file et envoyées au retour du réseau.
- Thème clair / sombre, interface pensée pour le mobile, installable sur l'écran d'accueil de l'iPhone.


Les flux
Chaque compte gère ses propres abonnements : il démarre sans aucun flux, les nomme et les range dans ses catégories.
- Ajout par simple adresse de site : Veille détecte le flux RSS ou Atom de la page.
- Import / export OPML depuis NetNewsWire, Feedly, Inoreader, Thunderbird… Les doublons sont ignorés.
- Par flux : activer / désactiver, tester, renommer, et remettre en non lu ses seuls articles.
- Collecte immédiate sur demande, sinon automatique toutes les 30 minutes.


Les comptes et la sécurité
- Deux rôles : lecteur, et administrateur qui gère les comptes (sans voir les flux des autres).
- Double authentification TOTP, optionnelle ou imposée par l'admin, avec « se souvenir de cet appareil ». Compatible Aegis, 2FAS, Proton Authenticator, etc.
- Mots de passe hachés avec scrypt, sessions en cookie
HttpOnly, blocage de 15 minutes après 5 échecs, CSP stricte, protection CSRF. - Aucun accès au réseau interne : le serveur refuse de télécharger une adresse en 127.0.0.1, 192.168.x, 10.x… même après redirection. Un compte ne peut donc pas s'en servir pour sonder le réseau local.
Les sauvegardes
Trois niveaux, sans rien installer de plus :
- Copie quotidienne automatique de la base, conservée 30 jours.
- Export par compte en
.json(flux, catégories, articles lus), restaurable en fusion ou en remplacement. - Archive complète chiffrée (ZIP AES-256, réservée à l'admin) : base, clé secrète, logo,
.envetdocker-compose.yml. Elle suffit à tout reconstruire sur une autre machine.
Comment c'est construit
Le point clé, c'est le collecteur côté serveur. Une adresse suivie par dix comptes n'est téléchargée qu'une fois, avec ETag / If-Modified-Since pour ne rien retransférer quand le flux n'a pas changé. Quand plus personne ne suit un flux, il est supprimé avec ses articles.
Côté technique, volontairement peu de choses :
- Node.js ≥ 22.13 avec le SQLite intégré (
node:sqlite) : pas de serveur de base de données. - Trois dépendances seulement : un parseur XML, la génération de QR codes pour la 2FA et le chiffrement des archives ZIP.
- Pas de framework côté navigateur : HTML, CSS et JavaScript.
- Lecteur de flux tolérant : RSS 2.0, Atom et RSS 1.0 (RDF), 4 Mo et 15 secondes maximum par téléchargement.
Mise en place
Prérequis
Un serveur avec Docker et Docker Compose. Veille consomme très peu : une petite VM ou un Raspberry Pi suffisent.
Installation
git clone https://github.com/xaviergregor/veille.git
cd veille
cp .env.example .env
vim .env
Dans .env, renseignez au minimum :
# Compte administrateur créé au premier démarrage (8 caractères minimum)
ADMIN_USER=admin
ADMIN_PASSWORD=un-vrai-mot-de-passe
# Clé de signature des cookies et de chiffrement des secrets 2FA
# (vide = générée automatiquement dans data/secret.key)
SECRET_KEY= # openssl rand -hex 32
Le fichier .env doit exister avant le premier démarrage : il est monté dans le conteneur pour la sauvegarde complète, et Docker créerait sinon un dossier à sa place.
Démarrez :
docker compose up -d --build
docker compose logs -f
Le log doit afficher « Compte administrateur « admin » créé. » puis une première collecte (vide, puisqu'aucun flux n'est encore suivi). L'interface répond sur http://serveur:3000.


Premiers flux
Connectez-vous, puis dans Mes flux :
- Ajouter un flux : collez l'adresse d'un site ou de son flux.
- ou Importer OPML : le dépôt fournit
exemples/flux-techno.opml, une quarantaine de flux techno déjà rangés par catégorie (sécurité, Linux, cloud, Apple, dev…).
Derrière un reverse proxy
Pour une exposition en HTTPS (Nginx Proxy Manager, Caddy, Traefik…), ajoutez dans .env :
TRUST_PROXY=1 # vraie IP du visiteur pour les logs et l'anti-bruteforce
COOKIE_SECURE=1 # cookies « Secure » : connexion uniquement en HTTPS
Dans ce cas, mieux vaut aussi n'écouter qu'en local dans docker-compose.yml : "127.0.0.1:3000:3000" au lieu de "3000:3000". Avec COOKIE_SECURE=1, la connexion ne fonctionne plus en HTTP direct sur le port 3000.
Votre logo (optionnel)
Déposez branding/logo.svg (ou .png, .webp, .jpg) à côté du docker-compose.yml, et éventuellement branding/logo-dark.svg pour le thème sombre. Il remplace la pastille violette dans l'en-tête et sur la page de connexion, sans redémarrage.
Réglages utiles
| Variable | Défaut | Rôle |
|---|---|---|
FETCH_INTERVAL |
30 |
Minutes entre deux collectes (5 à 1440) |
RETENTION_DAYS |
30 |
Durée de conservation des articles |
BACKUP_DAYS |
30 |
Copies quotidiennes conservées |
MAX_FEEDS_PER_USER |
300 |
Nombre de flux maximum par compte |
ADMIN_REQUIRE_2FA |
0 |
1 : 2FA imposée au compte admin dès sa première connexion |
TRUST_DAYS |
30 |
Durée de « se souvenir de cet appareil » (0 = désactivé) |
ALLOW_PRIVATE_FEEDS |
0 |
1 : autorise les flux hébergés sur le réseau local |
La liste complète est dans le README du dépôt.
Mise à jour
Toutes les données vivent dans data/ (base SQLite, clé, sauvegardes quotidiennes), qui n'est pas versionné :
cd veille
git pull
docker compose up -d --build
Avant une mise à jour majeure, une sauvegarde complète chiffrée depuis Comptes › Sauvegardes ne coûte rien.
Pour finir
Veille fait exactement ce dont j'avais besoin : une veille partagée entre mes appareils, sans dépendre d'un service en ligne, et que je peux ouvrir à d'autres personnes sans qu'elles voient mes flux. Le code est sous github.com/xaviergregor/veille ; les retours et suggestions sont les bienvenus.