Mealie auf einem VPS selbst hosten
Installieren Sie Mealie mit Docker Compose auf einem eigenen VPS. Importieren Sie Rezepte per Link und nutzen Sie Essensplan, Einkaufsliste, nginx, TLS und Backups.
Was ein selbst gehosteter Rezeptmanager leistet
Ein selbst gehosteter Rezeptmanager speichert Ihre Rezepte in einer Datenbank auf einem Server, den Sie selbst verwalten. Mealie ist die Lösung, für die sich die meisten Haushalte entscheiden. Sie fügen die Adresse einer Rezeptseite ein. Mealie liest daraus die Zutaten, die Zubereitungsschritte, die Anzahl der Portionen und die Zubereitungszeit. Den Beschreibungstext und die Werbung lässt es dabei außen vor. In Ihrer Sammlung landet nur das Rezept.
Der restliche Funktionsumfang der Anwendung ist überschaubar. Es gibt einen Wochenplan, in den Sie Rezepte per Drag-and-drop einfügen. Außerdem gibt es eine Einkaufsliste, die aus diesem Plan erstellt wird. Jede Person, die kocht, erhält ein eigenes Login. Die gesamte Anwendung läuft in einem Container. Zwischen Anfragen ist sie inaktiv. Deshalb reicht ein kleiner VPS aus.
Diese Anleitung verwendet Docker Compose. Wenn Ihnen die Begriffe services: und volumes: noch nicht bekannt sind, lesen Sie zuerst wie Docker-Compose-Dateien aufgebaut sind. Der gesamte folgende Inhalt besteht aus einer Compose-Datei und vier Befehlen.
Mealie mit Docker Compose installieren
Mealie veröffentlicht seine Images in der GitHub Container Registry. Im Juli 2026 lautet der aktuelle stabile Tag v3.22.0. Fixieren Sie eine Version, statt latest zu verwenden: Mit latest kann ein docker compose pull an einem beliebigen Tag Sie über eine Datenbankmigration hinweg auf eine Version aktualisieren, auf die Sie nicht vorbereitet waren.
sudo mkdir -p /srv/mealie
cd /srv/mealie
sudo nano docker-compose.ymlservices:
mealie:
image: ghcr.io/mealie-recipes/mealie:v3.22.0
container_name: mealie
restart: always
ports:
- "127.0.0.1:9925:9000"
deploy:
resources:
limits:
memory: 1000M
volumes:
- mealie-data:/app/data/
environment:
ALLOW_SIGNUP: "false"
PUID: 1000
PGID: 1000
TZ: Europe/Amsterdam
BASE_URL: https://recipes.example.com
volumes:
mealie-data:Vor dem Start sollten Sie zwei Zeilen prüfen.
Der Port ist als 127.0.0.1:9925:9000 und nicht als 9925:9000 angegeben. Der Container lauscht intern auf 9000, und der Host leitet 9925 dorthin weiter. Die Bindung an die Loopback-Adresse ermöglicht nginx den Zugriff auf Mealie, während das Internet keinen Zugriff erhält. Docker schreibt eigene Regeln in den Paketfilter. Deshalb ist ein einfaches 9925:9000 von außen erreichbar, selbst wenn Ihre Firewall den Port als geschlossen meldet. Dieses Verhalten sollten Sie einmal nachvollziehen: Siehe warum veröffentlichte Docker-Ports ufw ignorieren.
BASE_URL muss exakt die öffentliche Adresse sein, die Sie verwenden werden, einschließlich Schema und ohne abschließenden Schrägstrich. Mealie erzeugt daraus Links zum Zurücksetzen von Passwörtern und Einladungslinks. Wenn Sie http://localhost:9925 setzen, enthält die Einladung an Ihren Partner einen Link, der nur auf dem Server selbst funktioniert.
Starten Sie den Container und überwachen Sie den ersten Start.
sudo docker compose up -d
sudo docker compose logs -f mealieBeim ersten Start erstellt Mealie die SQLite-Datenbank und führt die Migrationen aus. Das dauert einige Sekunden. Sobald die Logs keine Migrationszeilen mehr ausgeben, prüfen Sie die Anwendung lokal.
curl -I http://127.0.0.1:9925Ein 200 OK bedeutet, dass die Anwendung läuft. Connection refused bedeutet, dass der Container nicht läuft. Führen Sie sudo docker compose ps aus und lesen Sie den Exit-Code. Ein Container, der mit Code 137 beendet wurde, wurde wegen Überschreitung des Speicherlimits von 1000M beendet. Das kommt bei den kleinsten Tarifen vor.
Erste Anmeldung und Deaktivieren der offenen Registrierung
Das Standardkonto ist changeme@example.com mit dem Passwort MyPassword. Melden Sie sich damit an und ändern Sie anschließend sofort beide Werte, weil diese Kombination in der Dokumentation steht und daher in jedem Scanner enthalten ist.
ALLOW_SIGNUP: "false" in der Compose-Datei ist absichtlich gesetzt. Bei geöffneter Registrierung kann jeder, der die Adresse findet, ein Konto in Ihrer Rezeptverwaltung anlegen. Bei deaktivierter Registrierung fügen Sie Personen über den Administrationsbereich hinzu. Dabei wird ein Einladungslink erzeugt, den Sie selbst versenden. Dieser Link wird aus BASE_URL erstellt. Deshalb ist dieser Wert wichtig. Wenn Sie später mehrere Anwendungen auf demselben Server betreiben und für alle dasselbe Passwort verwenden möchten, kann Mealie die Anmeldung an einen externen Identity Provider wie eine selbst gehostete Authentik-Instanz delegieren.
Mealie fasst Benutzer in einem Haushalt zusammen. Alle Personen in einem Haushalt teilen sich die Rezeptsammlung, den Speiseplan und die Einkaufsliste. Das entspricht dem Bedarf einer Familie. Separate Haushalte auf demselben Server behalten getrennte Sammlungen. Das ist für eine Wohngemeinschaft sinnvoll, wenn niemand einer Meinung über Sardellen ist.
Der Importer, der der eigentliche Grund für den Betrieb ist
Öffnen Sie die Rezeptsammlung, wählen Sie die Option zum Erstellen eines Rezepts aus einer URL und fügen Sie einen Link ein. Mealie ruft die Seite ab und sucht nach strukturierten Rezeptdaten, also nach dem maschinenlesbaren Block, den die meisten Rezeptseiten für Suchmaschinen einbinden. Wenn dieser Block vorhanden ist, wird der Import sauber und sofort durchgeführt.
Sie können auch ein Bild oder eingefügten Klartext importieren. Damit lässt sich beispielsweise ein Foto einer Kochbuchseite verarbeiten. Diese Varianten verwenden einen langsameren Verarbeitungspfad und sollten anschließend geprüft werden, da ein handgeschriebener Bruch leicht falsch gelesen wird.
Massenimporte werden über dieselbe Ansicht gestartet: Fügen Sie eine Liste von Adressen ein, jeweils eine pro Zeile, und Mealie verarbeitet sie im Hintergrund. Eine Sammlung mit zweihundert Lesezeichen lässt sich so in einem Durchgang übertragen.
Mahlzeitenpläne und die Einkaufsliste
Der Mahlzeitenplaner ist ein Kalender. Ziehen Sie ein Rezept auf einen Tag, um es einzuplanen. Die Einkaufsliste übernimmt anschließend die Zutaten der eingeplanten Rezepte in eine gemeinsame Liste und fasst doppelte Einträge zusammen. Wenn zwei Rezepte Zwiebeln benötigen, erscheint daher nur eine Zeile statt zwei.
Die Liste ist beim Einkaufen auf dem Smartphone als Live-Seite verfügbar. Da sie auf Ihrem eigenen Server gespeichert ist, sehen alle Personen im Haushalt gleichzeitig dieselbe Liste. Wenn eine Person Milch abhakt, wird sie auch auf dem Bildschirm der anderen Person entfernt.
nginx und TLS vorschalten
Mealie verwendet unverschlüsseltes HTTP und verwaltet keine Zertifikate selbst. Beenden Sie die Transport Layer Security (TLS) in einem vorgeschalteten nginx. Verweisen Sie zuerst mit einem DNS-A-Record auf Ihren Server, da der Zertifikatsschritt diesen Namen überprüft.
sudo apt update && sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/mealieserver {
listen 80;
server_name recipes.example.com;
client_max_body_size 64M;
location / {
proxy_pass http://127.0.0.1:9925;
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;
}
}sudo ln -s /etc/nginx/sites-available/mealie /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxnginx -t, syntax is ok und test is successful auszugeben, ist die entscheidende Prüfung. Führen Sie den Reload erst aus, wenn diese Prüfung erfolgreich ist. Andernfalls bleibt bei einer fehlerhaften Konfiguration die alte Konfiguration aktiv, und der Fehler wird bis zum nächsten Neustart verborgen.
client_max_body_size 64M ist erforderlich, weil der nginx-Standardwert bei 1 MB liegt. Beim Hochladen eines Rezeptfotos oder beim Wiederherstellen eines Backups über den Browser wird ein größerer Request-Body übertragen. Ohne diese Zeile erhalten Sie von nginx statt von Mealie einen 413 Request Entity Too Large. Deshalb erscheint im Anwendungslog überhaupt kein Eintrag.
Stellen Sie anschließend das Zertifikat aus. Dieser Schritt und der Timer für die Verlängerung werden unter ein Let's-Encrypt-Zertifikat für nginx mit certbot ausstellen beschrieben.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d recipes.example.comCertbot schreibt den Server-Block so um, dass er auf 443 lauscht, und fügt eine Weiterleitung von Port 80 hinzu. Rufen Sie die Website über https:// auf und prüfen Sie, ob der Browser das Zertifikat akzeptiert. Wenn Mealie geladen wird, die eigenen Links Sie aber zu http:// weiterleiten, steht in BASE_URL noch http. Korrigieren Sie diesen Wert und führen Sie anschließend sudo docker compose up -d aus, um den Container mit dem neuen Wert neu zu erstellen.
Mealie unter einem Unterpfad wie example.com/recipes bereitzustellen, funktioniert nicht, weil das Frontend nicht aus einem Unterpfad bereitgestellt werden kann. Verwenden Sie eine Subdomain.
Backups und was eine Wiederherstellung tatsächlich bewirkt
Alles, was Mealie verwaltet, liegt im Container unter /app/data/. Dabei handelt es sich um das Volume mealie-data. Wenn Sie dieses Volume kopieren, kopieren Sie Rezepte, Bilder und Datenbank gemeinsam.
sudo docker volume ls
sudo docker compose stop mealie
sudo docker run --rm -v mealie_mealie-data:/data -v "$PWD":/backup \
alpine tar czf /backup/mealie-data.tgz -C /data .
sudo docker compose start mealieDer Volume-Name enthält den Projektnamen als Präfix. Der Projektname entspricht dem Verzeichnis, das die Compose-Datei enthält. Unter /srv/mealie lautet der Name des Volumes mealie_mealie-data. Deshalb verwendet der erste Befehl docker volume ls: Verwenden Sie den Namen, den der Befehl ausgibt, und nicht den Namen aus dieser Anleitung. Stoppen Sie den Container vorher. SQLite schreibt häufig gerade Daten, sodass eine laufende Kopie möglicherweise eine nicht lesbare Wiederherstellung ergibt.
Mealie verfügt außerdem über eine eigene Backup-Seite im Administrationsbereich. Sie erstellt ein portables Archiv, das die Datenbank als JSON und Ihre Bilder enthält. Verwenden Sie diese Funktion, wenn Sie zwischen Servern umziehen. Das Archiv übersteht einen Versionswechsel, den eine einfache Dateikopie möglicherweise nicht übersteht. Die Wiederherstellung eines Archivs ist absichtlich destruktiv: Die aktuelle Datenbank wird vor dem Laden des Archivs gelöscht und dieser Vorgang kann nicht rückgängig gemacht werden. Nach Abschluss werden Sie abgemeldet.
Keine der beiden Kopien ist ein Backup, solange sie auf demselben Server liegt. Übertragen Sie das Archiv regelmäßig an einen anderen Ort. Dafür sind verschlüsselte Off-Server-Backups mit restic vorgesehen.
Mealie aktualisieren
cd /srv/mealie
sudo nano docker-compose.yml
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mealieErhöhen Sie die festgelegte Version in der Datei. Laden Sie anschließend das Image herunter und erstellen Sie den Container neu. Migrationen werden beim ersten Start des neuen Images ausgeführt. Erstellen Sie vor einem Wechsel der Hauptversion eine Kopie des Volumes. Wenn eine Migration auf halber Strecke fehlschlägt, bleibt eine Datenbank zurück, die das vorherige Image nicht mehr öffnen kann. Lesen Sie die Release Notes für alle Versionen zwischen Ihrer aktuellen und der neuen Version.
Wenn der Import fehlschlägt
Einige Websites veröffentlichen überhaupt keine strukturierten Rezeptdaten. Mealie importiert dann einen Titel mit einer leeren Zutatenliste. Das lässt sich nicht durch eine Konfiguration beheben. Fügen Sie den Rezepttext stattdessen manuell ein.
Andere Fehler werden durch einen Bot-Schutz vor der Rezept-Website verursacht. Dieser sendet Mealie eine Challenge-Seite statt des Rezepts. Mealie gibt sich bereits als Browser aus und wechselt den User-Agent, um dies zu vermeiden. Wenn eine Website die Anfrage weiterhin ablehnt, bestehen laut Dokumentation zwei Möglichkeiten: Leiten Sie den Scraper über einen Proxy mit besserem Ruf der IP-Adresse, oder betreiben Sie eine FlareSolverr-Instanz, die die Challenge in einem echten Browser löst. Beide Optionen sind freiwillig. Beide werden über Umgebungsvariablen im Container konfiguriert.
Ein Import, der fehlschlägt, weil Ihr Server die Website überhaupt nicht erreichen kann, ist ein anderes Problem. Testen Sie die Verbindung direkt auf dem Server mit curl -I https://the-site.example/recipe. Lesen Sie die Statuszeile, bevor Sie den Scraper als Ursache betrachten.
Wo es hineinpasst
Mealie ist eine gute erste Self-Hosted-Anwendung für einen Haushalt, weil die Personen, mit denen Sie zusammenleben, sie ohne Aufforderung verwenden werden. Die Aufgabe entspricht im Wesentlichen dem Betrieb Ihrer eigenen Fotobibliothek mit Immich, ist jedoch deutlich ressourcenschonender. Außerdem gehört sie zur größeren Liste der Anwendungen, deren Self-Hosting sich in diesem Jahr lohnt. Ein kleiner Server kann beides betreiben. Immich ist nicht die einzige Option für diese zweite Aufgabe. Wenn Sie noch entscheiden, sind die Mindestanforderungen an den Arbeitsspeicher und die Backup-Befehle von PhotoPrism und Immich unterschiedlich genug, um sie zu lesen, bevor Sie den restlichen Speicherplatz verplanen. Wenn der Haushalt neben den Mahlzeiten auch seine Pläne und Notizen verwaltet, ist ein selbst gehosteter AFFiNE-Arbeitsbereich wieder dieselbe Übung mit einer Compose-Datei. Er benötigt jedoch vier Container und deutlich mehr Arbeitsspeicher als Mealie. Prüfen Sie daher zuerst, welche Ressourcen auf dem Server noch verfügbar sind. Wenn der Haushalt neben den Mahlzeiten auch seine Trainingseinheiten erfassen möchte, verwaltet openGym die Workouts und verwendet denselben festgelegten Tag, dieselbe Compose-Datei und dasselbe Zertifikat, die Sie gerade eingerichtet haben. Der Abend nach dem Essen hat ebenfalls eine eigene Variante: Halcyon baut eine vorhandene Jellyfin-Bibliothek zu einer Videothek aus den 1990er-Jahren um, durch die Sie sich bewegen können. Dabei handelt es sich um einen weiteren kleinen Container vor etwas, das Sie bereits betreiben, und nicht um eine weitere Datenbank, die gesichert werden muss. Nicht alles in dieser Gruppe ist eine Haushaltsanwendung. Wenn dieselbe Gewohnheit irgendwann auch berufliche Aufgaben unterstützen soll, ist ein selbst gehosteter Chatwoot-Supportdesk wieder mit demselben festgelegten Tag und Zertifikat eingerichtet, dahinter jedoch mit Postgres, Redis und funktionierendem ausgehendem E-Mail-Versand. Das ist ein deutlich ressourcenintensiverer Mandant als eine Rezeptverwaltung und sollte auf einem eigenen Server betrieben werden.
FAQ
Warum schlägt der Import einer Rezept-URL fehl?
Dafür gibt es zwei häufige Ursachen. Entweder veröffentlicht die Seite keine strukturierten Rezeptdaten, sodass der Scraper nichts findet und Sie nur einen Titel ohne Zutaten erhalten, oder eine vorgeschaltete Bot-Schutzschicht liefert statt des Rezepts eine Challenge-Seite zurück. Im zweiten Fall kann Mealie auf einen Proxy mit besserer Reputation der IP-Adresse oder auf eine selbst gehostete FlareSolverr-Instanz verwiesen werden, die die Challenge in einem echten Browser löst. Prüfen Sie mit curl -I, ob Ihr Server die Seite überhaupt erreichen kann, bevor Sie etwas ändern.
Benötige ich PostgreSQL, oder reicht SQLite aus?
Für einen Haushalt reicht SQLite aus, und es ist die Standardeinstellung. Wechseln Sie zu PostgreSQL, wenn das Datenverzeichnis auf einem netzwerkgebundenen Speicher liegt, weil SQLite auf einem Netzwerkdateisystem Fehler wegen gesperrter Datenbanken erzeugt und die Datei beschädigen kann. Für Wiederherstellungen unter PostgreSQL muss der Datenbankbenutzer ein Superuser sein, da die Wiederherstellung vor dem Laden des Archivs alle Daten löscht.
Kann ich Mealie ohne Domainnamen ausführen?
Ja, in Ihrem eigenen Netzwerk. Setzen Sie BASE_URL auf die Adresse, die Sie tatsächlich eingeben werden, beispielsweise http://192.168.1.20:9925, und verzichten Sie auf nginx. Einladungs- und Links zum Zurücksetzen des Passworts werden aus BASE_URL erstellt. Ein falscher Wert erzeugt daher Links, die niemand sonst öffnen kann. Setzen Sie Mealie nicht über unverschlüsseltes HTTP dem Internet aus, weil die Anmeldedaten dann im Klartext übertragen werden.
Wie gebe ich meiner Familie eigene Anmeldedaten?
Lassen Sie ALLOW_SIGNUP auf "false" gesetzt und fügen Sie Personen im Administrationsbereich hinzu. Dort wird ein Einladungslink erzeugt, den Sie an die Personen senden. Ordnen Sie alle Personen, die eine Küche gemeinsam nutzen, demselben Haushalt zu, damit sie Rezepte, Speiseplan und Einkaufsliste gemeinsam verwenden. Getrennte Haushalte auf demselben Server behalten getrennte Sammlungen.
Was passiert mit meinen Rezepten, wenn ich Mealie nicht mehr ausführe?
Sie bleiben erhalten. Die Sicherung im Administrationsbereich schreibt Ihre Daten als JSON. Mealie kann Rezepte außerdem als einfache markdown-Dateien exportieren. Diese bleiben in jedem Texteditor ohne zusätzliche Software lesbar. Erstellen Sie einen Export, bevor Sie ihn benötigen, und prüfen Sie, ob Sie ihn öffnen können.