Installer FreshRSS sur un VPS Ubuntu 24.04
Installez FreshRSS 1.29.1 sur Ubuntu 24.04 avec Apache, PHP 8.3 et MariaDB : release tarball, virtual host, cron d’actualisation et API mobile.
Ce que vous allez mettre en place
Un lecteur RSS auto-hébergé est un lecteur de flux qui s’exécute sur un serveur que vous contrôlez. Personne ne peut ainsi l’arrêter ni modifier ce qu’il vous affiche. Ce guide installe FreshRSS sur un VPS Ubuntu 24.04 : Apache en frontal, PHP en arrière-plan, MariaDB pour le stockage et une tâche cron qui récupère les nouveaux articles. RSS (Really Simple Syndication) est le format de fichier qu’un site publie pour que des logiciels puissent lire ses articles. FreshRSS est l’application PHP qui collecte ces fichiers, conserve les articles et fournit une interface web ainsi qu’une API (interface de programmation d’application) utilisée par les applications mobiles.
L’installation est simple : décompresser une release, créer une base de données, écrire un virtual host et exécuter un programme d’installation en ligne de commande. La plupart des problèmes surviennent ensuite, notamment avec la tâche d’actualisation, les slashes encodés pour l’API mobile et les propriétaires des fichiers.
FreshRSS 1.29.1 est la release actuelle en juillet 2026 et nécessite PHP 8.1 ou une version ultérieure. Ubuntu 24.04 fournit PHP 8.3. Les packages de la distribution suffisent donc, et vous n’avez pas besoin d’un dépôt PHP tiers.
Partir d’une pile LAMP opérationnelle
FreshRSS est une application PHP classique. Elle nécessite donc la même base que les autres applications PHP. Si cette base n’est pas encore en place, suivez d’abord la procédure de configuration d’une pile LAMP sur Ubuntu 24.04, puis revenez ici. En résumé :
sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadbsystemctl status apache2 doit renvoyer active (running). Si Apache ne démarre pas, la cause habituelle est qu’un autre processus utilise déjà le port 80. sudo ss -ltnp | grep :80 l’identifie.
Les extensions PHP nécessaires à FreshRSS
FreshRSS considère libxml, cURL, JSON, PDO_MySQL, PCRE et ctype comme obligatoires. Il recommande également mbstring, iconv, Zlib et ZipArchive, ainsi que GMP sur un système 32 bits. Sur Ubuntu, elles sont fournies par les paquets de la distribution :
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2Vérifiez les extensions effectivement chargées par PHP avec php -m. L’absence d’une extension n’empêche pas le programme d’installation de démarrer. Elle bloque l’installation sur l’écran des prérequis, avec une ligne rouge indiquant le nom de l’extension. Il est donc préférable de vérifier maintenant, car cet écran est un endroit peu clair pour découvrir le problème. Le redémarrage d’Apache est nécessaire, car libapache2-mod-php conserve PHP dans le processus Apache. Le serveur web ne voit donc pas une extension nouvellement installée tant qu’il n’a pas redémarré.
Télécharger la version
Installez FreshRSS en dehors de la racine web par défaut et configurez Apache pour pointer vers ce répertoire. En séparant le répertoire de l’application de la racine des documents, seul le dossier public est accessible via HTTP.
cd /tmp
curl -fsSLO https://github.com/FreshRSS/FreshRSS/archive/refs/tags/1.29.1.tar.gz
tar xzf 1.29.1.tar.gz
sudo mv FreshRSS-1.29.1 /srv/freshrssDéfinissez maintenant les permissions, conformément aux exigences strictes de la documentation de FreshRSS : l’utilisateur du serveur web est propriétaire de l’arborescence, le groupe peut lire tous les fichiers et le groupe peut écrire dans ./data/.
sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/dataSi vous ignorez cette étape, l’installateur échoue lors de l’écriture de sa configuration, car PHP s’exécute sous www-data et www-data ne peut pas écrire dans un répertoire appartenant à root.
Créer la base de données
FreshRSS prend en charge SQLite, MariaDB, MySQL et PostgreSQL. SQLite ne nécessite aucune configuration et convient à une seule personne avec quelques centaines de flux. MariaDB est préférable lorsque plusieurs personnes partagent l’instance, car les écritures concurrentes du job d’actualisation et de l’interface web ne se disputent plus un seul verrou de fichier.
sudo mariadb -e "CREATE DATABASE freshrss CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "CREATE USER 'freshrss'@'localhost' IDENTIFIED BY 'ReplaceThisPassword';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON freshrss.* TO 'freshrss'@'localhost';"
sudo mariadb -e "FLUSH PRIVILEGES;"Utilisez utf8mb4 et non utf8. Les flux peuvent contenir des emoji et des caractères issus d’alphabets non latins. L’ancien encodage utf8 sur trois octets tronque le titre d’un article au premier caractère codé sur quatre octets.
L’hôte virtuel Apache
Le répertoire public est p/, et non la racine de l’arborescence. Tout le reste, notamment le fichier de configuration qui contient le mot de passe de votre base de données, se trouve au-dessus de la racine des documents. Apache ne le servira jamais.
<VirtualHost *:80>
ServerName rss.example.com
DocumentRoot /srv/freshrss/p/
<Directory /srv/freshrss/p>
AllowOverride AuthConfig FileInfo Indexes Limit
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/freshrss_error.log
CustomLog ${APACHE_LOG_DIR}/freshrss_access.log combined
AllowEncodedSlashes On
</VirtualHost>Enregistrez ce contenu dans /etc/apache2/sites-available/freshrss.conf, puis activez-le :
sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2configtest devrait afficher Syntax OK. AllowEncodedSlashes On semble facultative, mais elle est nécessaire : l’API Google Reader envoie des identifiants de flux contenant %2F. Sans cette directive, Apache les rejette. Les applications mobiles ne peuvent donc pas se synchroniser, alors que l’interface web fonctionne correctement.
Ajoutez HTTPS avant de vous connecter
Vous êtes sur le point de saisir un mot de passe sur ce site. Obtenez donc d’abord un certificat. Faites pointer un enregistrement A vers le serveur, puis suivez la procédure de configuration de Certbot pour Apache sur Ubuntu et exécutez sudo certbot --apache -d rss.example.com. Certbot réécrit l’hôte virtuel pour le port 443 et ajoute la redirection. Vérifiez avec curl -I https://rss.example.com/, qui doit renvoyer un 200 ou rediriger vers la page de connexion.
Exécuter l’installateur depuis la ligne de commande
FreshRSS propose un installateur dans le navigateur, mais la version en ligne de commande est reproductible et conserve la trace exacte de vos choix.
sudo -u www-data php /srv/freshrss/cli/do-install.php \
--default-user admin --auth-type form --environment production \
--base-url https://rss.example.com --language en --api-enabled \
--db-type mysql --db-host localhost --db-user freshrss \
--db-password 'ReplaceThisPassword' --db-base freshrss
sudo -u www-data php /srv/freshrss/cli/create-user.php \
--user admin --password 'a-long-passphrase' --api-password 'a-different-passphrase'Exécutez les deux commandes avec www-data. Si vous les exécutez en tant que root, les fichiers de configuration appartiennent à root. L’interface Web ne pourra alors plus enregistrer les paramètres. --environment production est également important, car le paramètre de développement affiche les notifications PHP dans la page.
Chargez https://rss.example.com/ et connectez-vous en tant que admin.
Pourquoi les flux ne s’actualisent pas automatiquement
Aucun processus n’interroge vos flux tant que vous ne le lui demandez pas. FreshRSS s’actualise lorsqu’un navigateur est ouvert dessus. Une instance que vous consultez deux fois par jour vous affiche donc des articles vieux de douze heures. La solution est le script fourni par le projet à cet effet, app/actualize_script.php, exécuté par cron.
sudo crontab -u www-data -eAjoutez une ligne :
*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1Vingt minutes est l’intervalle minimal raisonnable. Le script refuse d’actualiser un même flux plus souvent qu’une fois toutes les vingt minutes. Une planification plus fréquente ne ferait donc que consommer du CPU. Exécutez-le d’abord manuellement :
sudo -u www-data php /srv/freshrss/app/actualize_script.phpUne sortie normale indique le nom de chaque flux récupéré et se termine sans erreur PHP. Si aucune sortie ne s’affiche, l’utilisateur de cron est incorrect. Une erreur de permission sur data/ signifie que l’étape chmod -R g+w a été ignorée.
Ajouter vos premiers flux
Utilisez le bouton plus en haut à gauche de l’interface, collez l’adresse d’un site et FreshRSS détecte le lien du flux pour vous. La plupart des sites en publient encore un même lorsqu’ils ne l’affichent pas, généralement à l’adresse /feed, /rss ou /atom.xml. Les catégories sont des dossiers. Pour déplacer un flux entre deux catégories, faites-le glisser.
Si vous utilisez un autre lecteur, exportez-y un fichier OPML, puis importez-le depuis la page de gestion des abonnements. OPML (outline processor markup language) est le format standard des listes de flux, et tout lecteur qui mérite d’être utilisé prend en charge ce format. Une importation volumineuse est lente lors de la première actualisation, car chaque flux est récupéré une fois. Laissez donc le premier lancement de cron se terminer avant d’évaluer la vitesse.
Lisez-le sur votre téléphone
FreshRSS prend en charge l’API Google Reader, que presque toutes les applications RSS prennent en charge. Deux conditions doivent être remplies. Dans les paramètres d’authentification, l’option « Autoriser l’accès à l’API » doit être activée. Le flag --api-enabled ci-dessus l’a déjà activée. Dans votre profil, le champ du mot de passe API doit contenir une valeur. Il est volontairement distinct de votre mot de passe de connexion, car un téléphone est plus facile à perdre.
Accédez à https://rss.example.com/api/ et sélectionnez « Vérifier la configuration complète du serveur ». Une configuration fonctionnelle renvoie PASS. Une erreur à cette étape est presque toujours due à l’absence de la ligne AllowEncodedSlashes On. Dans l’application, indiquez l’adresse du serveur https://rss.example.com/api/greader.php, votre nom d’utilisateur FreshRSS et le mot de passe API comme mot de passe.
L’alternative Docker
Si vous préférez ne pas gérer PHP et Apache manuellement, le projet publie une image officielle freshrss/freshrss. Un fichier Compose suffit pour déployer l’application et sa base de données ensemble. Le compromis est classique : moins de composants à gérer sur l’hôte, mais une couche supplémentaire à diagnostiquer en cas de problème. Un reverse proxy reste nécessaire pour TLS (transport layer security). Si cette solution vous convient mieux, les bases de Docker Compose pour un VPS expliquent le format du fichier. La ligne cron devient alors docker exec --user www-data freshrss php ./app/actualize_script.php.
Sauvegardes et mises à niveau
Deux éléments conservent votre état : la base de données et /srv/freshrss/data/. Exportez la première avec sudo mysqldump freshrss > freshrss.sql, copiez le second et conservez les deux ailleurs que sur ce serveur. Votre liste d’abonnements mérite également un export OPML occasionnel, car ce fichier permet de recréer votre configuration de lecture avec n’importe quel logiciel RSS.
La mise à niveau consiste à décompresser une version plus récente dans le même répertoire, puis à exécuter de nouveau les commandes de propriété. FreshRSS applique ses propres migrations de base de données au chargement de la page suivante. Effectuez d’abord une sauvegarde, car une migration échouée sur une base de données que vous ne pouvez pas restaurer vous met dans une situation irrécupérable. Un lecteur est un service peu risqué à exécuter et un bon premier candidat si vous parcourez une liste de services qui méritent d’être auto-hébergés.
FAQ
Pourquoi mes flux ne se mettent-ils à jour que lorsque j’ouvre FreshRSS ?
Parce qu’aucun scheduler n’existe tant que vous n’en avez pas créé un. FreshRSS actualise les flux lorsqu’une session de navigateur est ouverte et ne fait rien lorsque l’onglet est fermé. Ajoutez la ligne cron qui appelle app/actualize_script.php en tant qu’utilisateur www-data, puis exécutez le script manuellement une fois et lisez sa sortie. L’absence de sortie signifie généralement que cron l’exécute avec le mauvais utilisateur et que PHP ne peut donc pas écrire dans data/.
Mon application mobile ne peut pas se connecter, mais le site web fonctionne. Pourquoi ?
L’API Google Reader place des barres obliques encodées (%2F) dans les chemins des requêtes, et Apache les rejette par défaut. Ajoutez AllowEncodedSlashes On dans le virtual host, puis rechargez Apache. Vérifiez la correction en ouvrant https://rss.example.com/api/ et en exécutant « Check full server configuration », qui devrait signaler PASS. Vérifiez également que le mot de passe de l’API est défini dans votre profil, car il est distinct de votre mot de passe de connexion.
Dois-je utiliser SQLite ou MariaDB ?
SQLite convient à un seul utilisateur, car rien n’est à installer et aucun mot de passe n’est à gérer. Utilisez MariaDB dès que plusieurs personnes lisent les flux sur l’instance, ou dès que vous dépassez quelques centaines de flux, car le job d’actualisation et l’interface web écrivent en même temps et le verrouillage d’un fichier unique devient une limite. Vous pourrez ensuite passer de l’un à l’autre avec les commandes d’export et d’import. Ce choix n’est donc pas définitif.
L’installateur échoue lorsqu’il écrit sa configuration. Quel est le problème ?
Sous Apache, PHP s’exécute en tant que www-data, et cet utilisateur ne peut pas écrire dans un répertoire appartenant à root. Réexécutez sudo chown -R www-data:www-data /srv/freshrss et sudo chmod -R g+w /srv/freshrss/data, puis relancez l’installateur. Si vous avez déjà exécuté l’installateur en ligne de commande en tant que root, supprimez les fichiers qu’il a créés sous data/ avant de réessayer, car le problème vient de leur propriétaire.
De quelles ressources serveur un lecteur RSS auto-hébergé a-t-il besoin ?
De très peu. Quelques centaines de flux sur une petite offre conviennent, car la charge se limite à de brèves périodes de récupération HTTP toutes les vingt minutes et la base de données reste peu volumineuse une fois les anciens articles supprimés. L’espace disque augmente avec la durée de conservation. Définissez donc une règle de purge des articles dans les paramètres d’archivage au lieu de tout conserver indéfiniment.