FreshRSS: der eigene RSS-Reader
Alle Nachrichtenquellen an einem Ort, ohne Algorithmus und Tracking: FreshRSS als selbstgehosteter RSS-Reader hinter Traefik – mit App-Anbindung.
Inhaltsverzeichnis
RSS ist das beste Nachrichtenformat, das die meisten vergessen haben: Du abonnierst Quellen direkt, ohne Algorithmus, ohne Werbung, ohne dass jemand mitliest, was du liest. FreshRSS bündelt all deine Quellen an einem selbstgehosteten Ort – und synchronisiert sogar mit den RSS-Apps auf dem Handy.
Was bauen wir?
Einen eigenen RSS-Reader mit FreshRSS (v1.30.4) hinter Traefik, der deine Nachrichtenquellen sammelt und im Hintergrund per Cron aktuell hält. Am Ende liest du Nachrichtenseiten, Blogs und Podcast-Feeds an einem Ort, gruppiert in Kategorien – und kannst über die eingebaute Google-Reader-API mobile Apps wie Reeder oder FeedMe anbinden. FreshRSS ist erfrischend leichtgewichtig: Es genügt SQLite, keine separate Datenbank nötig.
Voraussetzungen
- Ein Server mit laufendem Traefik und Docker Compose
- Eine Subdomain, die auf den Server zeigt – im Folgenden
DEINE_DOMAIN(z. B.rss.DEINE_DOMAIN)
VPS 1000 G12.5
4 vCore · 8 GB RAM · 128 GB SSD
ab 14,50 €/Monat
FreshRSS ist genügsam – der kleinste VPS reicht auch für viele Feeds.
💶 1 Monat gratis:
Einmal einlösbar, gilt für VPS 1000 G12.5. Im Warenkorb einlösen →
💶 5,95 € Gutschein für netcup-Neukunden: immer gültig · nicht für Domains und VPS Lite
Schritt für Schritt
Schritt 1: Compose-Datei anlegen
FreshRSS speichert alles in einem data-Verzeichnis (SQLite-Datenbank, Konfiguration, Cache). Lege das Projekt an:
mkdir -p /opt/freshrss && cd /opt/freshrssDie compose.yaml – ersetze DEINE_DOMAIN:
services:
freshrss:
image: freshrss/freshrss:1.30.4
restart: unless-stopped
volumes:
- ./data:/var/www/FreshRSS/data
- ./extensions:/var/www/FreshRSS/extensions
environment:
TZ: Europe/Berlin
CRON_MIN: '13,43'
networks: [proxy]
labels:
- "traefik.enable=true"
- "traefik.http.routers.freshrss.rule=Host(`DEINE_DOMAIN`)"
- "traefik.http.routers.freshrss.entrypoints=websecure"
- "traefik.http.routers.freshrss.tls.certresolver=le"
- "traefik.http.routers.freshrss.middlewares=freshrss-nur-ich"
- "traefik.http.middlewares.freshrss-nur-ich.ipallowlist.sourcerange=DEINE_IPV4/32,DEIN_IPV6_PRAEFIX::/64"
- "traefik.http.services.freshrss.loadbalancer.server.port=80"
networks:
proxy:
external: trueCRON_MIN ist ein nettes Detail des offiziellen Images: Der Start-Code schreibt daraus einen Cron-Eintrag im Container, der die Feeds zu den genannten Minuten (hier 13 und 43 jeder Stunde) automatisch aktualisiert – du brauchst keinen externen Timer.
Die beiden Verzeichnisse data und extensions legst du nicht selbst an: Der Container erzeugt sie beim ersten Start und setzt die Rechte selbst (root:www-data, Gruppenschreibrecht – zur Einordnung siehe Benutzer & Rechte). Das gilt auch auf gehärteten Servern mit UMASK 027.
freshrss-nur-ich lässt bis zum Ende der Einrichtung nur deine eigene Adresse durch, alle anderen bekommen 403 Forbidden. Solange noch kein Admin-Konto existiert, gehört die Instanz sonst dem, der die Seite zuerst aufruft – und Scanner finden neue Hostnamen über die öffentlichen Zertifikats-Logs mitunter schon Sekunden nach dem Start. Deine Adressen fragst du auf deinem eigenen Rechner ab, nicht auf dem Server: curl -4 -s https://ifconfig.me für die IPv4, curl -6 -s https://ifconfig.me für die IPv6 (davon die ersten vier Blöcke). Hast du kein IPv6, lass den zweiten Eintrag samt Komma weg – aber nur dann: Browser gehen bevorzugt per IPv6, und eine reine IPv4-Liste sperrt dich selbst aus. Mehr dazu in Traefik härten.
Schritt 2: Starten
docker compose up -dEin Blick auf den Containerstatus – Up und Port 80 nur containerintern, nach außen geht alles über Traefik:
docker compose psNAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
freshrss-freshrss-1 freshrss/freshrss:1.30.4 "./Docker/entrypoint…" freshrss 11 seconds ago Up 10 seconds 80/tcpPrüfe von deinem eigenen Rechner aus, dass FreshRSS mit gültigem HTTPS antwortet (die 302 ist die Weiterleitung zum Installations-Assistenten; vom Server aus kommt wegen freshrss-nur-ich nur 403):
curl -sI https://DEINE_DOMAIN/ | head -1HTTP/2 302Kommt hier ein Zertifikatsfehler statt der 302, hat Traefik das Zertifikat noch nicht – das dauert nach dem ersten Start ein paar Sekunden.
Schritt 3: Der Installations-Assistent
Öffne https://DEINE_DOMAIN/ im Browser. Der Assistent führt dich in fünf Schritten durch die Einrichtung – Sprache, Überprüfungen, Datenbank, allgemeine Konfiguration, Abschluss:

Schritt 2 listet die PHP- und Dateirechte-Prüfungen auf; mit dem offiziellen Image stehen dort nur grüne „OK!"-Zeilen, auch für das data-Verzeichnis. Wähle als Datenbanktyp SQLite (keine weiteren Angaben nötig), als Authentifizierung Webformular und lege dein Administrator-Konto mit einem starken Passwort an. Der letzte Schritt bestätigt „Glückwunsch! Der Installationsvorgang war erfolgreich." – erst der Klick auf Installation fertigstellen schließt die Einrichtung ab und bringt dich zur Anmeldung.
Alternative: Einrichtung per Kommandozeile
docker compose exec -u www-data freshrss ./cli/do-install.php --default-user admin --auth-type form --db-type sqlite --language de --base-url https://DEINE_DOMAIN, danach ./cli/create-user.php --user admin --password 'DEIN_PASSWORT'. Die --base-url ist dabei wichtig: Der grafische Assistent trägt sie von selbst ein, der CLI-Weg nicht – und ohne sie zeigt die Statusseite unter /api/ später eine falsche API-Adresse an.Ist die Installation fertiggestellt, nimm die Sperre wieder heraus: Lösch in der compose.yaml die beiden Zeilen mit freshrss-nur-ich und übernimm die Änderung:
docker compose up -dSchritt 4: Erste Feeds abonnieren
Klicke oben links auf Abonnementverwaltung → Feed oder Kategorie hinzufügen. Trage die Feed-URL einer Quelle ein (z. B. https://www.heise.de/rss/heise-atom.xml) und ordne sie einer Kategorie zu. FreshRSS erkennt das Feed-Format automatisch. Nach dem Hinzufügen mehrerer Quellen sieht die Verwaltung so aus:

Bestehende Feeds per OPML übernehmen
Schritt 5: Lesen
Zurück in der Leseansicht sammelt FreshRSS die Artikel aller Quellen chronologisch, gruppiert nach Kategorie. Ungelesene Zähler pro Feed, Sternchen für Favoriten, Volltextsuche – alles da:

Schritt 6: Handy-Apps anbinden (optional)
FreshRSS spricht die Google-Reader-API, sodass viele mobile Apps es als Sync-Backend nutzen können. Das sind zwei Schalter, nicht einer – und genau daran scheitert die erste App-Anmeldung meistens.
Zuerst der serverweite Schalter: Einstellungen → Administration → Authentifizierung → API-Zugriff erlauben, dann speichern. FreshRSS fragt vor den Administrationsseiten noch einmal dein Passwort ab; diese erneute Anmeldung gilt danach 20 Minuten.

Danach das persönliche Passwort: Einstellungen → Profil → API-Zugriff, dort ein eigenes API-Passwort vergeben – nicht dein Anmeldepasswort, denn es wird im Klartext übertragen und kann in Server-Logs landen. Auf derselben Seite verlinkt FreshRSS die Statusseite https://DEINE_DOMAIN/api/, die dir die korrekte API-Adresse nennt und die Konfiguration selbst testet.
In der App (z. B. Reeder, FeedMe, NetNewsWire) wählst du „FreshRSS“ oder „Google Reader API“, trägst https://DEINE_DOMAIN/api/greader.php, deinen Benutzernamen und das API-Passwort ein – und liest unterwegs synchron weiter.
Feeds aus dem eigenen Netz seit 1.30
127.0.0.1 oder auf einem Nachbarcontainer wird mit URL is not allowed to be resolved abgewiesen. Brauchst du so eine Quelle (etwa eine RSS-Bridge im selben Compose-Netz), gibst du sie gezielt frei: INTERNAL_HOST_ALLOWLIST: rss-bridge:80 als Umgebungsvariable im Compose – ein Eintrag pro Host, host:port oder CIDR. Ein * erlaubt alles und hebelt den Schutz aus.Wenn es nicht funktioniert
Die Seite antwortet mit 403 Forbidden. Die Sperre aus Schritt 1 lässt deine Adresse nicht durch. Meist fehlt die IPv6 oder sie hat sich geändert – frag beide Adressen erneut ab (siehe dort), korrigiere sourcerange und starte mit docker compose up -d neu.
Nach der Einrichtung begrüßt dich wieder Schritt 1 des Assistenten. Abgeschlossen ist die Installation erst mit dem Klick auf „Installation fertigstellen“ im letzten Schritt – wer das Browserfenster vorher schließt, landet beim nächsten Aufruf erneut im Assistenten. Dann einfach noch einmal durchlaufen und diesmal bis zum Ende klicken. Um Dateirechte musst du dich dabei nicht kümmern: Das offizielle Image korrigiert Gruppe und Rechte des data-Verzeichnisses bei jedem Start selbst – auch bei einem aus dem Backup zurückgespielten Ordner.
Feeds werden nicht automatisch aktualisiert. Prüfe zuerst, ob der Cron-Eintrag im Container überhaupt existiert: docker compose exec freshrss crontab -l muss eine Zeile ausgeben, die mit deinen CRON_MIN-Minuten beginnt (13,43 * * * * …). Fehlt sie, war CRON_MIN beim Start nicht gesetzt – Variable ergänzen und docker compose up -d. Was der letzte Lauf gemacht hat, steht im Container unter /tmp/FreshRSS.log (docker compose exec freshrss tail /tmp/FreshRSS.log). Manuell anstoßen kannst du jederzeit mit docker compose exec -u www-data freshrss ./cli/actualize-user.php --user admin.
Die Handy-App verbindet sich nicht und meldet einen Serverfehler. Antwortet https://DEINE_DOMAIN/api/greader.php mit 503 Service Unavailable!, fehlt der serverweite Schalter aus Schritt 6: Ohne den Haken bei „API-Zugriff erlauben“ unter Administration → Authentifizierung nützt auch ein gesetztes API-Passwort nichts. Mit beidem antwortet die API auf eine Anmeldung mit 200 und liefert ein Auth-Token zurück.
Ein Feed aus dem eigenen Netz bleibt leer. Seit 1.30 blockiert FreshRSS lokale Ziele; im Protokoll steht URL is not allowed to be resolved bzw. Fetching this URL is not allowed, because the host’s IP is not in the allowlist. Lösung ist die Umgebungsvariable INTERNAL_HOST_ALLOWLIST (siehe Kasten oben) – oder dieselbe Liste unter Administration → Systemeinstellungen. Bleibt ein Feed aus dem öffentlichen Netz leer, ist die URL meist eine HTML-Seite statt des Feeds; suche im Seitenquelltext nach application/rss+xml.
Nach einiger Zeit fehlen ältere Artikel. Das ist die Archivierung, und sie ist absichtlich streng voreingestellt: FreshRSS hält Artikel drei Monate und höchstens 200 pro Feed vor, mindestens aber 50 – Favoriten und mit Label versehene Artikel bleiben unangetastet. Wer länger blättern will, erhöht die Werte unter Einstellungen → Archivierung oder pro Feed in dessen Einstellungen; die Datenbank wächst dann entsprechend.
Dein Problem ist nicht dabei? Alle Fehlermeldungen durchsuchen →
Wartung & Backups
- Updates. Setze den Image-Tag (
freshrss/freshrss:1.30.4) auf die neue Version, danndocker compose pull && docker compose up -d; FreshRSS wandert seine Datenbank beim Start automatisch mit. Größere Sprünge kündigt das Projekt in den Release-Notes an – 1.30 war etwa eine Sicherheitsversion mit einer bewussten Verschärfung (siehe Kasten zu lokalen Feeds). Den Rest erledigt dein normaler Update-Prozess. - Backup. Der gesamte Zustand liegt im
data-Ordner (SQLite-Datenbank + Konfiguration). Ihn ins Restic-Backup aufnehmen – dann sind Abos, Kategorien und gelesene Markierungen gesichert. Eine laufende SQLite-Datei kopiert man aber ungern mitten im Schreibvorgang:docker compose exec -u www-data freshrss ./cli/db-backup.phplegt vorher eine konsistente Kopie alsdata/users/<benutzer>/backup.sqliteab, die dein Backup dann einsammelt. Zusätzlich lohnt ein regelmäßiger OPML-Export deiner Feed-Liste als menschenlesbares, reader-unabhängiges Backup. - Aufwand ist gering. FreshRSS ist ein „einmal einrichten, dann läuft es"-Dienst. Die einzige wiederkehrende Aufgabe ist das Pflegen deiner Feed-Liste – unter Statistiken → Inaktive Feeds siehst du gebündelt, welche Quellen seit Monaten nichts mehr geliefert haben, und mistest sie aus.
Zuletzt aktualisiert: 31.10.2026
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken


