Pourquoi auto-héberger FreshRSS sur un VPS
FreshRSS est un agrégateur de flux RSS/Atom écrit en PHP, conçu pour être discret en ressources tout en gérant des milliers d'articles. Le self-hosting sur VPS résout trois problèmes que les services fermés ne traitent pas : la pérennité (votre veille ne disparaît pas du jour au lendemain), la confidentialité (personne ne profile vos abonnements) et la fraîcheur (vous définissez la fréquence de rafraîchissement via cron, sans quota imposé). Un VPS, contrairement à un hébergement mutualisé, vous donne un accès SSH complet, le droit de lancer un conteneur Docker et de planifier des tâches — exactement ce dont FreshRSS a besoin pour rafraîchir les flux en arrière-plan.
Bénéfices concrets du FreshRSS auto-hébergé
- API native compatible Fever et Google Reader : synchronisez avec Reeder, FeedMe ou Fluent Reader sur mobile.
- Extension GReader / scraping : récupérez le contenu complet d'articles tronqués grâce aux filtres XPath.
- Multi-utilisateurs avec quotas par compte : idéal pour partager une instance au sein d'une agence.
- Empreinte mémoire minime (200 à 300 Mo) : tourne sur le plus petit des VPS sans broncher.
- Rafraîchissement piloté par cron : vous décidez si les flux se mettent à jour toutes les 5 minutes ou toutes les heures.
- Sauvegarde triviale : une base SQLite/MySQL et un dossier de données suffisent à tout restaurer.
Prérequis techniques
FreshRSS est l'une des applications les plus frugales du self-hosting. Comptez 1 vCPU et 1 Go de RAM pour une instance personnelle à quelques utilisateurs ; 10 Go de disque suffisent largement, l'essentiel étant occupé par l'historique d'articles. Côté logiciel : Docker et le plugin Docker Compose installés sur le VPS, un nom de domaine (ou sous-domaine type rss.votredomaine.com) pointé en A vers l'IP du serveur, et un port 80/443 ouvert pour le reverse proxy. PHP n'a pas à être installé sur l'hôte : l'image officielle freshrss/freshrss embarque tout.
Déployer FreshRSS pas à pas
Préparer le VPS et Docker
Connectez-vous en SSH, mettez à jour le système (
apt update && apt upgrade -y), puis installez Docker :curl -fsSL https://get.docker.com | sh. Ajoutez votre utilisateur au groupe docker :usermod -aG docker $USER. Vérifiez avecdocker compose version. Créez le dossier projet :mkdir -p /opt/freshrss && cd /opt/freshrss.Écrire le docker-compose.yml
Créez le fichier
docker-compose.ymlavec le contenu suivant :services: freshrss: image: freshrss/freshrss:latest container_name: freshrss restart: unless-stopped environment: CRON_MIN: "*/20" TZ: "Europe/Paris" volumes: - ./data:/var/www/FreshRSS/data - ./extensions:/var/www/FreshRSS/extensions ports: - "127.0.0.1:8080:80"Le port est lié uniquement à
127.0.0.1: seul le reverse proxy local y accède, le port n'est jamais exposé sur l'IP publique.Configurer nginx comme reverse proxy
Installez nginx :
apt install -y nginx. Créez/etc/nginx/sites-available/freshrss:server { listen 80; server_name rss.votredomaine.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }Activez le vhost :
ln -s /etc/nginx/sites-available/freshrss /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx.Obtenir le certificat TLS avec Certbot
Installez Certbot et le plugin nginx :
apt install -y certbot python3-certbot-nginx. Émettez le certificat :certbot --nginx -d rss.votredomaine.com. Certbot modifie automatiquement le vhost nginx pour écouter sur 443 et rediriger HTTP vers HTTPS. Le renouvellement automatique est activé d'office via le timer systemd certbot.Lancer le conteneur
Démarrez la stack depuis
/opt/freshrss:docker compose up -d. Suivez l'initialisation :docker compose logs -f. Le conteneur applique les migrations et crée l'arborescence de données au premier démarrage. Vérifiez ensuite que FreshRSS répond :curl -I https://rss.votredomaine.com.Terminer l'installation web
Ouvrez
https://rss.votredomaine.comdans votre navigateur. L'assistant vous demande de choisir le backend de base de données : sélectionnez SQLite pour un usage personnel (fichier unique, pas de service à gérer), ou MySQL si plusieurs dizaines d'utilisateurs sont prévus. Créez le compte administrateur avec un mot de passe fort.Activer l'API
Rendez-vous dans Profil → Gestion de l'API. Cochez « Activer l'API GReader/Fever » et définissez un mot de passe d'API distinct de votre mot de passe principal (il sera transmis en clair par certains clients). Notez l'URL de base de l'API :
https://rss.votredomaine.com/api/greader.php. Vous pouvez tester immédiatement aveccurl -X POST https://rss.votredomaine.com/api/greader.php/accounts/ClientLogin -d [email protected]&Passwd=<apipass>.Importer votre OPML
Exportez vos abonnements depuis votre ancien lecteur (Feedly, Inoreader…) au format OPML. Dans FreshRSS, allez dans Abonnements → Import/Export → Importer un fichier OPML. Vos catégories et flux sont recréés en quelques secondes. Vérifiez le premier rafraîchissement manuel :
docker compose exec freshrss php ./cli/actualize.php.Vérifier le cron automatique
La variable
CRON_MIN=*/20configure le cron interne du conteneur pour rafraîchir tous les flux toutes les 20 minutes. Confirmez qu'il tourne :docker compose exec freshrss crontab -l. Si vous préférez piloter depuis l'hôte, désactivez le cron interne (CRON_MIN=vide) et ajoutez un crontab système :*/15 * * * * docker exec freshrss php /var/www/FreshRSS/app/actualize_script.php 2>&1 | logger -t freshrss.
Pour les sites qui ne publient qu'un extrait dans leur flux, installez l'extension officielle « FreshRSS Content Selector » : configurez un sélecteur CSS (ex : article.post-content) par abonnement et FreshRSS ira récupérer le texte intégral à chaque rafraîchissement. Combinez-la avec l'extension de filtres pour masquer automatiquement les articles sponsorisés détectés par mot-clé.
Configuration avancée de FreshRSS
Une fois l'instance de base opérationnelle, trois axes d'optimisation font passer FreshRSS d'un simple lecteur à un véritable outil de veille :
Extensions : RSS-Bridge et FullTextRss. Copiez l'extension dans /opt/freshrss/extensions/, puis activez-la dans Extensions dans l'interface. RSS-Bridge génère un flux RSS pour des sites qui n'en proposent pas (Twitter/X public, Instagram, LinkedIn), sous forme d'un bridge exécuté sur votre VPS. FullTextRss (version auto-hébergée de la bibliothèque FiveFilters) complète les articles tronqués en extrayant le corps HTML selon des règles de site prédéfinies — plus de 2 000 sites sont déjà configurés dans la base de règles communautaire.
Fréquence de rafraîchissement. La valeur CRON_MIN=*/20 convient pour la majorité des veilles. Pour des sources critiques (alertes de sécurité, cours de bourse), descendez à */5. Pour réduire la charge sur votre VPS avec beaucoup d'abonnements inactifs, montez à */60. FreshRSS respecte aussi les en-têtes ETag et Last-Modified des serveurs HTTP : si un flux n'a pas changé, le rafraîchissement est quasi gratuit en bande passante.
SQLite vs MySQL. SQLite suffit jusqu'à quelques centaines de milliers d'articles et une poignée d'utilisateurs ; sa simplicité (un seul fichier) en fait la option adaptée pour un usage personnel. Au-delà de 5 utilisateurs simultanés ou de 500 000 articles, MySQL (ou MariaDB) offre de appropriées performances sur les requêtes de lecture. La migration SQLite → MySQL est possible via l'outil CLI convert-db.php fourni dans le conteneur.
L'API FreshRSS pour vos agents IA et automatisations
FreshRSS est l'un des rares agrégateurs auto-hébergés à implémenter deux API standard : l'API Google Reader (/api/greader.php) et l'API Fever (/api/fever.php). Ces API, documentées publiquement, permettent une intégration sans friction avec des dizaines d'outils d'automatisation.
Intégration n8n. Dans un workflow n8n, utilisez le nœud HTTP Request avec l'authentification Basic (identifiants API FreshRSS). Déclenchez le workflow sur les nouveaux articles non lus en interrogeant le endpoint GReader : GET /api/greader.php/reader/api/0/stream/contents/user/-/state/com.google/reading-list?n=20&xt=user/-/state/com.google/read. Chaînez avec un nœud OpenAI pour résumer chaque article, puis envoyez le résumé dans Slack ou par email. Le tout sans quitter votre infrastructure.
Intégration Make (ex-Integromat). Le module HTTP de Make permet les mêmes appels REST. Un scénario typique : toutes les heures, récupérer les articles étoilés, les enrichir avec un LLM via un webhook, et les pousser dans Notion ou Airtable pour constituer une base de connaissance structurée.
Agents IA. Les frameworks d'agents comme LangChain ou LlamaIndex peuvent interroger directement l'API FreshRSS pour alimenter un RAG (Retrieval-Augmented Generation) sur votre veille personnelle. Votre instance devient une source de données privée, structurée et fraîche, inaccessible aux modèles publics.
FreshRSS vs Miniflux vs Tiny Tiny RSS
Faites défiler le tableau
| Critère | FreshRSS | Miniflux | Tiny Tiny RSS |
|---|---|---|---|
| Langage / stack | PHP + SQLite/MySQL | Go (binaire unique) | PHP + PostgreSQL |
| RAM minimale | ~50 Mo (sans Docker) | ~20 Mo | ~100 Mo |
| API standard | Google Reader + Fever | Miniflux REST + Fever | Google Reader (plugin) |
| Extensions / plugins | Riche (>30 officielles) | Limitées (filtres natifs) | Plugins tiers nombreux |
| Licence | AGPL-3.0 | Apache-2.0 | GPL-3.0 |
Sauvegarder et migrer FreshRSS
L'un des avantages du self-hosting est la maîtrise complète de vos données. Deux niveaux de sauvegarde couvrent tous les scénarios :
Export OPML (abonnements). Depuis Abonnements → Import/Export → Exporter en OPML, vous générez un fichier XML portant tous vos flux et catégories. C'est la sauvegarde minimale : elle vous permet de réimporter votre liste de flux sur n'importe quelle instance FreshRSS ou tout autre lecteur RSS compatible. Automatisez-la avec un crontab : 0 3 * * * docker exec freshrss php /var/www/FreshRSS/cli/export-opml-file.php > /opt/backups/freshrss-opml-$(date +%F).xml.
Sauvegarde complète (base + données). Pour conserver aussi l'historique de lecture et les étoiles, sauvegardez le volume Docker entier : rsync -a /opt/freshrss/data/ /opt/backups/freshrss-data-$(date +%F)/. Si vous utilisez SQLite, la base est dans data/users/<user>/non_default_feeds.sqlite et data/users/<user>/default.sqlite. Pour MySQL, un mysqldump suffit.
Migration entre VPS. Le processus est linéaire : (1) arrêtez le conteneur source (docker compose stop) ; (2) copiez le dossier data/ sur le nouveau VPS via rsync ou scp ; (3) déployez la même docker-compose.yml sur le nouveau VPS et démarrez ; (4) mettez à jour le DNS A record vers la nouvelle IP. Temps total pour une instance personnelle : moins de 10 minutes, zéro perte de données.
Dépannage : 4 erreurs fréquentes
1. Cron inactif — les flux ne se mettent plus à jour. Symptôme : la colonne « Dernière mise à jour » reste figée. Vérifiez d'abord que le cron interne tourne : docker compose exec freshrss crontab -l. Si la sortie est vide, la variable CRON_MIN est absente ou vide dans votre docker-compose.yml. Ajoutez CRON_MIN: "*/20" sous environment: et relancez le conteneur (docker compose up -d --force-recreate).
2. Flux qui ne se met jamais à jour malgré un cron actif. Cause la plus fréquente : le flux retourne systématiquement une erreur HTTP 429 (rate-limit) ou 403. Vérifiez dans Abonnements → Gérer → Dernière erreur. Pour un site qui bloque les requêtes sans User-Agent, ajoutez dans la configuration avancée du flux un User-Agent explicite (ex : FreshRSS/1.24 (+https://rss.votredomaine.com)). Pour un flux derrière Cloudflare, RSS-Bridge avec le bridge CloudFlare contourne le challenge JS.
3. Erreur SSL « certificate verify failed ». Survient quand le conteneur FreshRSS tente de joindre un flux HTTPS dont le certificat est auto-signé ou expiré. Deux options : ignorer la vérification SSL pour ce flux spécifique (case à décocher dans les options avancées de l'abonnement), ou mettre à jour les CA du conteneur si toute la pile SSL est cassée (docker compose exec freshrss update-ca-certificates).
4. Extension FullTextRss muette — le contenu reste tronqué. Vérifiez que l'extension est bien activée dans Extensions et que l'URL du service FullTextRss est correcte dans sa configuration. Si vous utilisez la version auto-hébergée, testez l'URL directement dans le navigateur : https://votre-ftr.domain.com/extract.php?url=<url_article>. Une réponse JSON vide indique que le sélecteur du site n'est pas dans la base de règles — créez un fichier de règles custom dans site_patterns/ et montez-le comme volume Docker.
Cas d'usage : veille technologique pour développeur
Ajoutez les flux GitHub releases de chaque dépendance de votre projet (https://github.com/<owner>/<repo>/releases.atom), le flux Hacker News (https://news.ycombinator.com/rss), les blogs des mainteneurs principaux de votre écosystème, et les feeds CVE de votre runtime et OS.
FreshRSS livre la timeline brute — sans tri algorithmique, sans posts sponsorisés. Créez une règle de marquage automatique : tout article contenant « security advisory » ou « breaking change » reçoit une étoile et déclenche une notification ntfy sur votre téléphone. Vous obtenez le signal, sans le bruit des plateformes sociales.