Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Server & Netzwerk 14.09.2026 · 13 min Lesezeit

Miniflux 2.3.3 mit Docker Compose installieren und betreiben

Miniflux 2.3.3 mit PostgreSQL per Docker Compose einrichten: compose.yaml, erster Start mit Healthcheck, Feeds und API, Reverse Proxy mit TLS, Backup per pg_dump, Update und typische Fehler.

Geprüft am 16.10.2026 · für Miniflux 2.3.3

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Kompakter schwarzer Heimserver neben Zeitungsstapel und Kaffeetasse auf Holztisch vor unscharfer Stadtkulisse

Herstellerwarnungen, Security-Advisories und Release-Notes kommen bei vielen Administratoren als Newsletterflut im Postfach an. Ein selbst gehosteter Feed-Reader bündelt diese Quellen an einer Stelle, ohne Trackingpixel und ohne Cloud-Dienst, der jeden Lesevorgang protokolliert. Miniflux 2 besteht nur aus einer Go-Binärdatei und einer PostgreSQL-Datenbank. Diese Anleitung zeigt Installation, Erstkonfiguration, Reverse Proxy, Backup und Update von Miniflux 2.3.3 mit Docker Compose.

Voraussetzungen

Miniflux selbst ist sehr genügsam: Das Image miniflux/miniflux:2.3.3 war im Test 13.157.104 Byte groß, also rund 13 MB. Den Ressourcenbedarf bestimmt PostgreSQL. Für einige Dutzend Feeds und wenige Benutzer reichen 1 CPU-Kern und 1 GB RAM, ein kleiner Server mit 2 Kernen und 4 GB RAM bietet reichlich Reserve, etwa wenn weitere Dienste darauf laufen.

  • Linux-Server mit Docker Engine und Docker Compose v2. Im Test liefen Docker 29.1.3 und Compose 2.40.3 auf Ubuntu (x86_64).
  • Architektur: Das Projekt veröffentlicht Images für amd64, arm64, arm/v7, arm/v6 und riscv64, ein Raspberry Pi genügt also.
  • Speicher: wenige hundert MB für Images und Datenbank, mehr erst bei sehr vielen Feeds und langen Aufbewahrungsfristen.
  • Für den Zugriff aus dem Netz: eine Subdomain (im Beispiel feeds.example.org) und ein Reverse Proxy wie Nginx, Caddy oder Traefik mit TLS-Zertifikat.
EckdatumWert
Imageminiflux/miniflux:2.3.3 (auch auf ghcr.io und quay.io)
Datenbankpostgres:18-alpine
Port8080, nur an 127.0.0.1 gebunden
Volumeminiflux-db unter /var/lib/postgresql
Wichtige VariablenDATABASE_URL, RUN_MIGRATIONS, CREATE_ADMIN, BASE_URL, LISTEN_ADDR

Schritt 1: Projektordner und Zugangsdaten anlegen

Legen Sie einen Ordner an, zum Beispiel /opt/miniflux. Die Zugangsdaten gehören nicht in die Compose-Datei, sondern in eine .env-Datei im selben Ordner, die Docker Compose automatisch einliest. Ersetzen Sie die Platzhalter durch eigene, lange Passwörter.

# Datei: /opt/miniflux/.env
# Passwort der PostgreSQL-Datenbank, mindestens 24 Zeichen
POSTGRES_PASSWORD=bitte-hier-ein-eigenes-langes-passwort-eintragen
# Anmeldename des ersten Administrators
ADMIN_USERNAME=admin
# Passwort des ersten Administrators, mindestens 20 Zeichen
ADMIN_PASSWORD=bitte-hier-ein-eigenes-langes-passwort-eintragen

Die Datei enthält Klartextgeheimnisse. Da sie nur von Docker Compose auf dem Host gelesen wird und nicht in den Container gelangt, dürfen Sie sie auf den Eigentümer beschränken:

# Zugriff auf den Eigentümer beschränken
chmod 600 /opt/miniflux/.env
# Eigentümer prüfen
ls -l /opt/miniflux/.env

Wer strenger arbeiten will, nutzt die von Miniflux dokumentierten Varianten mit Suffix _FILE, etwa ADMIN_PASSWORD_FILE oder DATABASE_URL_FILE, und übergibt die Geheimnisse als Docker-Secrets.

Verifizieren: ls -l /opt/miniflux/.env zeigt -rw------- und Ihren Benutzer als Eigentümer, die Datei enthält keine Platzhalter mehr.

Schritt 2: compose.yaml erstellen

Speichern Sie im selben Ordner die Datei compose.yaml. Sie entspricht der getesteten Konfiguration, nur lag der Port im Test auf 38080 statt 8080.

services:
  miniflux:
    image: miniflux/miniflux:2.3.3
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@db/miniflux?sslmode=disable
      - RUN_MIGRATIONS=1
      - CREATE_ADMIN=1
      - ADMIN_USERNAME=${ADMIN_USERNAME}
      - ADMIN_PASSWORD=${ADMIN_PASSWORD}
      - BASE_URL=https://feeds.example.org/
      - LISTEN_ADDR=0.0.0.0:8080
    healthcheck:
      test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
      interval: 10s
      timeout: 5s
      retries: 5
  db:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=miniflux
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=miniflux
    volumes:
      - miniflux-db:/var/lib/postgresql
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "miniflux"]
      interval: 10s
      start_period: 30s
volumes:
  miniflux-db:

Die Punkte, auf die es ankommt:

  • Feste Version: Das Projekt empfiehlt ausdrücklich, eine Versionsnummer statt latest zu verwenden. Sonst holt jedes docker compose pull ungeplant eine neue Version samt Migrationen.
  • Port nur auf Loopback: 127.0.0.1:8080:8080 macht Miniflux nur für den Reverse Proxy auf demselben Host erreichbar. Ein offenes 8080:8080 würde an einer Host-Firewall wie ufw vorbei auf allen Interfaces lauschen.
  • Startreihenfolge: condition: service_healthy lässt Miniflux erst starten, wenn PostgreSQL bereit ist. Ohne diese Bedingung beendet sich Miniflux beim ersten Start mangels Datenbank und läuft in eine Neustartschleife.
  • Migrationen und Admin: RUN_MIGRATIONS=1 führt die SQL-Migrationen automatisch aus, CREATE_ADMIN=1 legt mit ADMIN_USERNAME und ADMIN_PASSWORD den ersten Administrator an.
  • Adressen: BASE_URL muss die spätere öffentliche HTTPS-Adresse sein, denn daraus erzeugt Miniflux Links und den Cookie-Pfad. LISTEN_ADDR=0.0.0.0:8080 ist im Container nötig, weil der Standard 127.0.0.1:8080 den Dienst nur im Container erreichbar machen würde.
  • Datenpfad: PostgreSQL 18 legt seine Daten unter /var/lib/postgresql ab, Version 17 und älter unter /var/lib/postgresql/data. Der Pfad muss zur Hauptversion passen.

Verifizieren: docker compose config --quiet im Ordner /opt/miniflux läuft ohne Ausgabe und ohne Warnung über fehlende Variablen durch.

Schritt 3: Stack starten und ersten Start prüfen

Laden Sie die Images und starten Sie den Stack:

# In das Projektverzeichnis wechseln
cd /opt/miniflux
# Images herunterladen
docker compose pull
# Stack im Hintergrund starten
docker compose up -d
# Status der Container inklusive Healthcheck anzeigen
docker compose ps

Im Test standen beide Container nach kurzer Zeit auf Up (healthy). Das Startlog zeigt, was Miniflux beim ersten Start erledigt:

# Logs des Miniflux-Containers anzeigen
docker compose logs miniflux
# Erwartete Zeilen beim ersten Start:
# Running database migrations current_version=0 latest_version=132
# Created new admin user username=admin user_id=1
# Starting HTTP server listen_address=0.0.0.0:8080

Die Datenbank wird beim ersten Start von Schema 0 auf 132 gehoben, deshalb dauert dieser Start etwas länger als alle folgenden. Danach entsteht der Administrator mit der ID 1, zuletzt startet der HTTP-Server. Für das Monitoring eignet sich der Endpunkt /healthcheck, weil er auch die Datenbankverbindung abdeckt. Ein reiner Portcheck würde eine abgestürzte Datenbank nicht bemerken.

# Healthcheck-Endpunkt abfragen, HTTP-Status ausgeben
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/healthcheck
# Antwortkörper ausgeben
curl -s http://localhost:8080/healthcheck

Die Version fragen Sie im Container ab. Ein Aufruf von /version im Browser leitet ohne Anmeldung nur auf die Loginseite um.

# Versionsnummer aus dem laufenden Container auslesen
docker compose exec -T miniflux /usr/bin/miniflux -version

Verifizieren: docker compose ps zeigt beide Dienste als healthy, /healthcheck liefert 200 und den Text OK, die Versionsabfrage gibt 2.3.3 aus.

Schritt 4: Anmelden, Kategorien und Feeds anlegen

Melden Sie sich mit den Daten aus der .env an, lokal etwa über einen SSH-Tunnel auf Port 8080, später über Ihre Proxy-Adresse. Legen Sie zuerst Kategorien an, denn jeder Feed gehört zu genau einer Kategorie. Bewährt hat sich eine Trennung nach Dringlichkeit: Security-Advisories täglich, Release-Notes der eingesetzten Produkte wöchentlich, allgemeine Branchennews nach Bedarf.

Beim Hinzufügen eines Abonnements akzeptiert Miniflux auch die Adresse der Webseite und sucht den Feed selbst. Unterstützt werden Atom, RSS 1.0 und 2.0 sowie JSON Feed. Bestehende Abonnements übernehmen Sie per OPML-Import in den Einstellungen. OPML überträgt Feeds und Kategorien, aber keine gelesenen Artikel und keine Lesezeichen.

Miniflux-Formular New feed mit URL-Feld, Kategorieauswahl und Schaltfläche Find a feed
Unter Feeds, Add feed genügt die Adresse der Webseite, Find a feed sucht den Feed selbst.

Für automatisierte Prüfungen eignet sich die API. Im Test lieferte /v1/me HTTP 200 mit is_admin: true, das Anlegen eines Feeds HTTP 201 mit {"feed_id":1}:

# Eigenes Benutzerprofil abfragen, liefert HTTP 200
curl -u admin:PASSWORT http://localhost:8080/v1/me
# Feed per API anlegen, liefert HTTP 201
curl -u admin:PASSWORT -X POST http://localhost:8080/v1/feeds \
  -H "Content-Type: application/json" \
  -d '{"feed_url":"https://borncity.com/blog/feed/","category_id":1}'

Anschließend zeigte GET /v1/feeds den Feed mit parsing_error_count 0, und GET /v1/entries belegte 20 abgerufene Einträge. Für den Dauerbetrieb empfiehlt die Dokumentation API-Schlüssel statt Basic Auth: Sie erzeugen sie in den Einstellungen unter API Keys und senden sie im Header X-Auth-Token. Ein Schlüssel lässt sich einzeln widerrufen.

Entfernen Sie nach dem ersten erfolgreichen Login CREATE_ADMIN, ADMIN_USERNAME und ADMIN_PASSWORD aus der compose.yaml und führen Sie docker compose up -d erneut aus. Die Dokumentation sieht das ausdrücklich vor, und das Admin-Kennwort steht dann nicht mehr in der Prozessumgebung. Der Miniflux-Prozess läuft übrigens nicht als root, im Test ergab die Prüfung uid=65534(nobody):

# Benutzerkontext im laufenden Container prüfen
docker compose exec -T miniflux id

Nach dem Abruf zeigt die Feedliste Zähler und letzte Prüfung, die Startseite Unread die neuen Einträge:

Miniflux-Feedliste mit einem abonnierten Feed, 20 Einträgen und dem Zeitpunkt der letzten Prüfung
Feedliste: 20 von 20 Einträgen ungelesen, letzte Prüfung gerade eben, kein Fehler.
Miniflux-Ansicht Unread mit 20 ungelesenen Einträgen aus einem abonnierten IT-Blog
Ansicht Unread mit den abgerufenen Einträgen des Feeds.

Verifizieren: Der neue Feed erscheint in der Oberfläche mit Artikeln und ohne Fehlerzähler, docker compose exec miniflux env | grep ADMIN liefert nach dem Neustart keine Ausgabe mehr.

Schritt 5: Reverse Proxy mit TLS einrichten

Ohne TLS gingen Zugangsdaten und Sitzungscookie im Klartext übers Netz. Miniflux bleibt deshalb auf der Loopback-Adresse, ein Reverse Proxy terminiert TLS. Das folgende Beispiel für Nginx folgt der Projektdokumentation und ergänzt den TLS-Teil:

server {
    server_name feeds.example.org;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/feeds.example.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/feeds.example.org/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_redirect off;
        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;
    }
}

X-Forwarded-Proto teilt Miniflux mit, dass die Verbindung außen bereits verschlüsselt ist, sonst entstehen Weiterleitungen auf HTTP. Ohne X-Forwarded-For kennt Miniflux die IP-Adresse des Besuchers nicht. Setzen Sie zusätzlich in der compose.yaml die Variable HTTPS=1: Laut Dokumentation erzwingt sie das Secure-Flag für Cookies und sendet den HSTS-Header. Fertige Beispiele für Caddy und Traefik liegen im Repository unter contrib/docker-compose, für den Betrieb in einem Unterverzeichnis hat die How-To-Seite eigene Beispiele.

Verifizieren: curl -I https://feeds.example.org/healthcheck liefert HTTP/2 200, nach HTTPS=1 enthält eine Antwort den Header strict-transport-security, und die Anmeldung im Browser bleibt bestehen.

Schritt 6: Backup einrichten und Wiederherstellung kennen

Feeds, Kategorien, Artikel, Benutzer und Lesestatus liegen ausschließlich in PostgreSQL. Der Miniflux-Container hält keine Daten und ist jederzeit ersetzbar. Im Test erzeugte dieser Befehl eine 76 KB große, gültige SQL-Datei:

# In das Projektverzeichnis wechseln
cd /opt/miniflux
# Datenbank als SQL-Dump sichern
docker compose exec -T db pg_dump -U miniflux miniflux > /var/backups/miniflux-$(date +%F).sql
# Ergebnis prüfen, Größe und Kopfzeile
ls -lh /var/backups/miniflux-$(date +%F).sql
head -5 /var/backups/miniflux-$(date +%F).sql

Die Option -T ist wichtig. Ohne sie weist Docker ein Pseudo-Terminal zu, und die umgeleitete Ausgabe enthält Steuerzeichen. Genau so produzieren Backup-Skripte im Cronjob unbemerkt unbrauchbare Dateien. Zum Zurückspielen stoppen Sie Miniflux, legen die Datenbank neu an und spielen den Dump ein:

# Miniflux stoppen, damit niemand während der Wiederherstellung schreibt
docker compose stop miniflux
# Bestehende Datenbank löschen und neu anlegen
docker compose exec -T db dropdb -U miniflux miniflux
docker compose exec -T db createdb -U miniflux miniflux
# Dump einspielen
docker compose exec -T db psql -U miniflux -d miniflux < /var/backups/miniflux-2026-09-14.sql
# Miniflux wieder starten
docker compose start miniflux
# Zustand prüfen
docker compose ps

Spielen Sie diesen Ablauf einmal auf einem separaten Host durch, bevor Sie sich im Ernstfall darauf verlassen. Ein gelegentlicher OPML-Export über die Weboberfläche ergänzt den Dump als kleines, lesbares Notfallnetz für die Feedliste.

Verifizieren: Die Dump-Datei ist größer als einige KB, head -5 zeigt die Kopfzeile PostgreSQL database dump, und nach einer Probe-Wiederherstellung stehen alle Feeds wieder in der Oberfläche.

Schritt 7: Miniflux aktualisieren

Die Upgrade-Dokumentation des Projekts warnt ausdrücklich vor blinden Updates: Lesen Sie vor jedem Versionswechsel die Release-Notes. Danach ziehen Sie einen Dump, tragen den neuen Tag in der compose.yaml ein und erzeugen den Container neu. RUN_MIGRATIONS=1 sorgt für die Schemaänderungen.

# Zuerst sichern, ohne Ausnahme
docker compose exec -T db pg_dump -U miniflux miniflux > /var/backups/miniflux-vor-update.sql
# Danach in der compose.yaml den neuen Image-Tag eintragen
# Neues Image herunterladen
docker compose pull
# Container mit neuem Image neu erzeugen
docker compose up -d
# Migrationsausgabe im Log kontrollieren
docker compose logs --tail 50 miniflux

Ein Rollback per altem Image-Tag funktioniert nicht zuverlässig: Nach den Migrationen liegt das Schema auf einem neueren Stand, und Miniflux bringt keine Abwärtsmigrationen mit. Der sichere Rückweg ist das alte Image zusammen mit dem Dump von vor dem Update, eingespielt in eine frisch angelegte Datenbank.

Verifizieren: Das Log zeigt die Migrationen ohne Fehler, die Versionsabfrage aus Schritt 3 meldet die neue Version, /healthcheck liefert wieder OK.

Typische Fehler

  • Nach einem Wechsel der PostgreSQL-Hauptversion sind alle Feeds weg. Das Volume hängt am falschen Pfad, Miniflux sieht eine leere Datenbank und legt sie neu an. Die Daten liegen meist noch im Volume. Prüfen Sie mit docker compose exec -T db ls -la /var/lib/postgresql, wo sie liegen, und passen Sie die Volume-Zeile an. Führen Sie nicht voreilig docker compose down -v aus, das löscht das Volume endgültig.
  • HTTP 500 beim Anlegen eines Feeds per API. Im Test antwortete POST /v1/feeds auf eine nicht existierende Feed-URL mit HTTP 500 und {"error_message":"fetcher: resource not found (404 status code)"}, im Log stand Unable to fetch feed. Der Fehler liegt bei der Quelle, nicht beim Server. Werten Sie error_message aus, statt den Dienst neu zu starten.
  • Einzelne Feeds liefern Fehler, andere nicht. Oft blockiert ein Bot-Schutz beim Anbieter. Miniflux erlaubt je Feed einen eigenen User-Agent, eigene Cookies und das Abschalten von HTTP/2, global auch einen Proxy über HTTP_CLIENT_PROXY. Prüfen Sie zuerst die Fehlermeldung des Feeds.
  • Login springt hinter dem Proxy zur Anmeldemaske zurück. BASE_URL stimmt nicht exakt mit der öffentlichen Adresse überein (Schema, Domain, abschließender Schrägstrich), oder der Proxy setzt X-Forwarded-Proto nicht.
  • Miniflux startet in einer Schleife neu. Prüfen Sie docker compose logs db. Häufige Ursache ist ein nachträglich geändertes POSTGRES_PASSWORD: Bei einem bereits initialisierten Volume wirkt die Variable nicht mehr, das alte Passwort gilt weiter.

Häufige Fragen

Kann Miniflux mehrere Benutzer verwalten?

Ja. Der Administrator legt weitere Konten an, jedes Konto pflegt eigene Abonnements und Kategorien. Ein Rollenmodell mit Gruppen gibt es nicht.

Welche Datenschutzfunktionen bringt Miniflux mit?

Laut Projektbeschreibung entfernt Miniflux Zählpixel und Tracking-Parameter wie utm_source oder fbclid, sendet keinen Referrer, blockiert externes JavaScript per Content Security Policy und bindet YouTube über youtube-nocookie.com ein. Ein Medien-Proxy kann Bilder über die eigene Instanz ausliefern, gesteuert über MEDIA_PROXY_MODE (Standard http-only).

Eignet sich Miniflux als Artikelarchiv?

Nein. Alte Einträge räumt Miniflux nach konfigurierbaren Fristen auf. Für eine dauerhafte Ablage ist ein Read-it-later-System wie Wallabag besser geeignet.

Gibt es Metriken für Prometheus?

Ja. METRICS_COLLECTOR=1 aktiviert laut Dokumentation den Endpunkt /metrics. Zugriff erlauben Sie über METRICS_ALLOWED_NETWORKS (Standard 127.0.0.1/8), optional mit METRICS_USERNAME und METRICS_PASSWORD.

Wie entferne ich Miniflux wieder vollständig?

Sichern Sie zuerst Dump und OPML-Export. docker compose down entfernt nur die Container, erst down -v löscht das Volume und damit alle Daten unwiderruflich:

# Vorher sichern
cd /opt/miniflux
docker compose exec -T db pg_dump -U miniflux miniflux > /var/backups/miniflux-final.sql
# Container stoppen und entfernen, Volume bleibt erhalten
docker compose down
# Erst wenn die Daten wirklich weg dürfen: Volume mit entfernen
docker compose down -v
# Images entfernen, falls nicht mehr benötigt
docker image rm miniflux/miniflux:2.3.3 postgres:18-alpine

Fazit

Miniflux ist ein Feed-Reader mit sehr geringem Betriebsaufwand: zwei Container, ein Volume, ein Healthcheck-Endpunkt und ein pg_dump im Cronjob. Das kleine Image und der Betrieb als nobody halten die Angriffsfläche klein. Wer mehr Funktionen und Erweiterungen braucht, findet sie bei FreshRSS, zahlt dafür aber mit mehr Pflege. Entscheidend für einen stabilen Betrieb sind die feste Versionsnummer, der passende PostgreSQL-Datenpfad und der Dump vor jedem Update.

Weiterführende Anleitungen und Quellen

MinifluxDocker ComposeRSSSelfhostingPostgreSQLFeed-Reader