Zum Inhalt springen
Alles Automatisch
Videos

Installation

Mealie selbst hosten: Rezepte per Foto und Home Assistant

Für alle ab
Für Mitglieder freigeschaltet

Früher Zugang für Kanalmitglieder

Das Video läuft schon, nur noch nicht für alle.

Kanalmitglieder sehen es jetzt. Für alle erscheint es am Sonntag, 15. November, um 9 Uhr. Die komplette Anleitung kannst du heute schon lesen, sie steht direkt darunter.

Mitglieder seit 3. Nov.Für alle am So., 15. Nov.
noch 12 Tage

Ich habe mir Mealie angeschaut, eine selbst gehostete Rezeptverwaltung mit Essensplaner und Einkaufsliste. Bei mir läuft sie in einem schlanken LXC-Container auf Proxmox. Ein Foto von einem handgeschriebenen Rezept ist nach rund 30 Sekunden sauber angelegt, dafür hängt Claude von Anthropic als KI dran. Abends zeigt das Küchen-Tablet in Home Assistant mit Rezeptfoto, was heute auf den Tisch kommt. Getestet habe ich das Ganze mit Mealie v3.28.0, Home Assistant 2026.10.1 und Proxmox VE 9.2. Die komplette YAML steht direkt in den Schritten unten, damit du sie einfach kopieren kannst.

Was du brauchst

Die Anforderungen sind eigentlich überschaubar. Der Container ist klein, nur für die KI-Funktionen und das Dashboard brauchst du ein bisschen mehr.

  • Einen Proxmox-Host mit rund 1,5 GB freiem RAM und 10 GB Speicher
  • Das Debian-13-Template in Proxmox (debian-13-standard)
  • Home Assistant ab 2024.8, für alle Aktionen aus diesem Artikel ab 2026.9
  • Für die KI-Funktionen einen API-Key von Anthropic (über platform.claude.com), abgerechnet nach Verbrauch
  • Für das Dashboard aus dem Marketplace (früher HACS): Mushroom und card-mod (oder UIX, das card-mod ersetzt)

Schritt 1: Den Container in Proxmox anlegen

Ein unprivilegierter LXC reicht völlig. Docker im Container braucht die Optionen nesting und keyctl. Auf dem Proxmox-Host sieht das so aus:

bash
1pveam update
2pveam available | grep debian-13
3pveam download local debian-13-standard_13.6-1_amd64.tar.zst
4
5pct create 108 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst \
6  --hostname mealie \
7  --cores 2 --memory 1536 --swap 512 --rootfs local-lvm:10 \
8  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
9  --features nesting=1,keyctl=1 --unprivileged 1 --onboot 1 \
10  --timezone Europe/Berlin
11pct start 108

Die Container-ID 108 und den Speicher local-lvm passt du an dein System an. Im Router gibst du dem Container danach eine feste Adresse, denn Home Assistant und die Rezeptbilder hängen an dieser URL.

Schritt 2: Docker installieren

Im Container (pct enter 108) installierst du Docker aus dem offiziellen Repository:

bash
apt update && apt install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable" > /etc/apt/sources.list.d/docker.list
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Schritt 3: Mealie mit Docker Compose starten

Lege die Datei /opt/mealie/compose.yaml an. Die Version ist fest gepinnt, damit ein Update eine bewusste Entscheidung bleibt. BASE_URL ist die Adresse, unter der du Mealie aufrufst. Die THEME_*-Zeilen sind optional und färben Mealie in deinen eigenen Farben.

yaml
1services:
2  mealie:
3    image: ghcr.io/mealie-recipes/mealie:v3.28.0
4    container_name: mealie
5    restart: unless-stopped
6    ports:
7      - "9000:9000"
8    deploy:
9      resources:
10        limits:
11          memory: 1000M
12    volumes:
13      - ./data:/app/data
14    environment:
15      TZ: Europe/Berlin
16      BASE_URL: http://192.168.178.50:9000
17      ALLOW_SIGNUP: "false"
18      DEFAULT_GROUP: Zuhause
19      DEFAULT_HOUSEHOLD: Familie
20      UVICORN_WORKERS: "1"
21      THEME_LIGHT_PRIMARY: "#F0665B"
22      THEME_LIGHT_ACCENT: "#2E8B7A"
23      THEME_LIGHT_SECONDARY: "#10172B"
24      THEME_LIGHT_INFO: "#2E8B7A"
25      THEME_DARK_PRIMARY: "#F0665B"
26      THEME_DARK_ACCENT: "#89C9BA"
27      THEME_DARK_SECONDARY: "#A9B4C8"
28      THEME_DARK_INFO: "#89C9BA"

192.168.178.50 ersetzt du durch die Adresse deines Containers. Dann startest du Mealie:

bash
cd /opt/mealie && docker compose up -d

Nach rund einer Minute ist Mealie unter http://<deine-ip>:9000 erreichbar. Die Erstanmeldung läuft mit changeme@example.com und dem Passwort MyPassword. Direkt danach gehst du auf Einstellungen → Benutzereinstellungen → Benutzerprofil verwalten, trägst deine eigene E-Mail-Adresse ein und speicherst mit Aktualisieren. Anschließend setzt du über Passwort ändern ein neues Passwort (Aktuelles Passwort, Neues Passwort, Passwort bestätigen, Aktualisieren).

Mit ALLOW_SIGNUP: "false" kann sich niemand selbst registrieren, weitere Familienmitglieder lädst du einfach ein. Ein Update ist später genau eine Zeile: Tag in der compose.yaml hochsetzen, dann docker compose pull && docker compose up -d.

Schritt 4: Deutsche Einheiten und Lebensmittel laden

Damit Mealie Zutaten wie „2 EL Tomatenmark“ sauber in Menge, Einheit und Lebensmittel zerlegt, braucht es deutsche Stammdaten:

  1. Einstellungen → Datenverwaltung
  2. Oben auf die Auswahl (zeigt zunächst „Lebensmittel“) klicken → Einheiten wählen, dann unten rechts unter der Tabelle den grünen Button Musterdaten → Sprache wählen → Bestätigen
  3. Dasselbe für Lebensmittel. Dabei legt Mealie auch die passenden Bezeichnungen an (sie sortieren die Einkaufsliste nach Abteilungen).

Abkürzungen wie „Pck.“ oder Mehrzahlformen kennt Mealie danach leider noch nicht alle. Die trägst du beim ersten Rezept nach: Im Zutaten-Parser (Rezept bearbeiten → Parsen) bietet Mealie z. B. „Füge „Pck.“ als Alias für Packung hinzu“ an. Ab dann erkennt es die Schreibweise in jedem Rezept.

Schritt 5: Kochbücher anlegen

Kochbücher sind gespeicherte Filter und stehen danach in der Seitenleiste. Unter Kochbücher → Erstellen legst du zum Beispiel diese an:

  • „Hauptgerichte“ mit der Kategorie Hauptgericht
  • „Backen“ mit der Kategorie Kuchen
  • „Vegetarisch & vegan“ mit den Schlagworten vegetarisch oder vegan

Jedes neue Rezept mit passender Kategorie landet automatisch im richtigen Buch.

Schritt 6: Claude als KI-Anbieter einrichten

Mealie spricht jede OpenAI-kompatible Schnittstelle an. Anthropic bietet so eine an, dadurch läuft Claude ohne Umweg.

  1. Auf platform.claude.com legst du unter API Keys einen eigenen Key nur für Mealie an. Ein eigener Key lässt sich später einzeln sperren, ohne andere Dienste zu treffen.
  2. In Mealie gehst du auf Einstellungen → Benutzereinstellungen (öffnet die Profilseite) → im Abschnitt „Gruppe“ die Karte „Gruppen-Einstellungen“ → Karte „KI-Anbieter-Einstellungen“ → Anbieter erstellen. Dort trägst du diese Werte ein:
FeldWert
AnbieternameClaude (Anthropic)
API-Keydein Key aus der Console
Basis-URLhttps://api.anthropic.com/v1/
Modellclaude-sonnet-5-5
  1. Den neuen Anbieter wählst du als Standard-Anbieter und als Bildanbieter aus. Einen Audio-Anbieter kann Claude nicht stellen, der Import aus Videos bleibt damit aus.

Danach steht unter Erstellen → Mit KI importieren bereit: Foto eines handgeschriebenen Rezepts, kopierter Text oder ein Link. Ein Foto dauerte bei mir rund 30 Sekunden, Zutaten und Schritte kamen sauber getrennt an. Anthropic nennt die OpenAI-kompatible Schnittstelle selbst keine Lösung für den Dauerbetrieb. Für ein paar Rezepte pro Woche läuft sie im Test allerdings zuverlässig.

Schritt 7: Fotos in den Zubereitungsschritten

Bilder zu einzelnen Schritten lädst du als Anhang ans Rezept und bindest sie im Schritt ein. Wichtig: Mealie filtert style-Angaben auf wenige Eigenschaften (Farbe, Hintergrundfarbe, Schriftstil und Schriftstärke, Textdekoration, Textausrichtung). Größenangaben wie width im style fallen weg, das HTML-Attribut width bleibt erhalten. Ohne Breite läuft das Bild am Handy über den Rand.

html
<img src="/api/media/recipes/REZEPT_ID/assets/schritt-1.webp" width="100%">

Die Rezept-ID liefert die API unter /api/recipes/<slug> im Feld id.

Schritt 8: Mealie in Home Assistant verbinden

Für die Mealie-Integration brauchst du zuerst einen Token aus Mealie.

  1. In Mealie gehst du auf Einstellungen → Benutzereinstellungen → Karte „API-Token“ (Link „Verwalte Deine API-Token“) → Token-Name „Home Assistant“ → Erzeugen. Den Token kopierst du sofort, Mealie zeigt ihn nur einmal. (Die Karte erscheint nur, wenn unter Benutzereinstellungen → „Benutzerprofil verwalten“ das Häkchen „Erweiterte Funktionen anzeigen (API-Schlüssel, Webhooks und Datenverwaltung)“ gesetzt ist.)
  2. In Home Assistant: Einstellungen → Geräte & Dienste → Integration hinzufügen → Mealie
  3. URL http://<deine-ip>:9000 eintragen und den API-Token einfügen. „SSL-Zertifikat überprüfen“ spielt ohne https keine Rolle.

Danach hast du unter anderem diese Entitäten:

EntitätInhalt
calendar.mealie_abendessenEssensplan Abendessen, dazu Frühstück, Mittagessen, Nachtisch, Beilage, Snack, Getränk
todo.mealie_<listenname> (z. B. todo.mealie_einkaufsliste, wenn die Liste in Mealie „Einkaufsliste“ heißt)Eine Entität pro Mealie-Einkaufsliste, abhakbar aus HA heraus
sensor.mealie_rezepteAnzahl der Rezepte, dazu Kategorien, Tags, Werkzeuge, Benutzer

Dazu kommen Aktionen wie „Essensplan abrufen“, „Essensplan aufstellen“, „Zufälligen Essensplan aufstellen“ und „Rezept importieren“.

Schritt 9: Das Abendessen mit Foto als Sensor

Die Kalender-Entität kennt nur den Namen des Gerichts. Für das Foto fragt ein Template-Sensor den Essensplan ab und baut daraus eine Bild-Entität. Home Assistant lädt das Bild selbst vom Mealie-Server, deshalb klappt es auch unterwegs über Nabu Casa ohne Mixed-Content-Fehler.

Die config_entry_id findest du unter Einstellungen → Werkzeuge → Aktionen. Dort wählst du „Essensplan abrufen“ (mealie.get_mealplan), suchst bei „Mealie-Instanz“ im Feld „Integration“ die Mealie-Integration aus und wechselst oben rechts auf „YAML-Modus“.

Das Ganze kommt in die Datei packages/mealie.yaml (Packages müssen in der configuration.yaml eingebunden sein):

yaml
1template:
2  - triggers:
3      - trigger: homeassistant
4        event: start
5      - trigger: time_pattern
6        minutes: "/10"
7      - trigger: state
8        entity_id: calendar.mealie_abendessen
9      - trigger: event
10        event_type: mealie_refresh
11    actions:
12      - action: mealie.get_mealplan
13        data:
14          config_entry_id: DEINE_CONFIG_ENTRY_ID
15          start_date: "{{ now().date() | string }}"
16          end_date: "{{ now().date() | string }}"
17        response_variable: plan
18        continue_on_error: true
19      - variables:
20          d_name: >-
21            {% set e = (plan.mealplan if plan is defined and plan.mealplan is defined else []) | selectattr('entry_type', 'eq', 'dinner') | list %}
22            {% if e and e[0].recipe %}{{ e[0].recipe.name }}{% elif e and e[0].title %}{{ e[0].title }}{% endif %}
23          d_id: >-
24            {% set e = (plan.mealplan if plan is defined and plan.mealplan is defined else []) | selectattr('entry_type', 'eq', 'dinner') | list %}
25            {{ e[0].recipe.recipe_id if e and e[0].recipe else '' }}
26          d_slug: >-
27            {% set e = (plan.mealplan if plan is defined and plan.mealplan is defined else []) | selectattr('entry_type', 'eq', 'dinner') | list %}
28            {{ e[0].recipe.slug if e and e[0].recipe else '' }}
29          d_time: >-
30            {% set e = (plan.mealplan if plan is defined and plan.mealplan is defined else []) | selectattr('entry_type', 'eq', 'dinner') | list %}
31            {{ e[0].recipe.total_time if e and e[0].recipe and e[0].recipe.total_time else '' }}
32    sensor:
33      - name: Mealie Abendessen heute
34        unique_id: mealie_dinner_today
35        icon: mdi:pot-steam
36        state: "{{ d_name if d_name else 'Nichts geplant' }}"
37        attributes:
38          slug: "{{ d_slug }}"
39          recipe_id: "{{ d_id }}"
40          total_time: "{{ d_time }}"
41          url: >-
42            {{ 'http://192.168.178.50:9000/g/zuhause/r/' ~ d_slug if d_slug
43               else 'http://192.168.178.50:9000/household/mealplan/planner/view' }}
44    image:
45      - name: Mealie Abendessen Foto
46        unique_id: mealie_dinner_today_image
47        availability: "{{ d_id | length > 0 }}"
48        url: >-
49          {{ 'http://192.168.178.50:9000/api/media/recipes/' ~ d_id ~ '/images/original.webp'
50             if d_id else 'http://192.168.178.50:9000/favicon.ico' }}

Die Adresse 192.168.178.50 und die Gruppe zuhause (aus DEFAULT_GROUP) passt du an. Nach dem Neuladen der Template-Entitäten gibt es sensor.mealie_abendessen_heute und image.mealie_abendessen_foto. Wer nicht zehn Minuten warten will, feuert unter Einstellungen → Werkzeuge → Ereignisse (Tab) mit dem Ereignistyp mealie_refresh über „Ereignis auslösen“ das Ereignis.

Schritt 10: Die Karte „Heute auf dem Tisch“

Das ist eine Mushroom-Template-Karte mit dem Rezeptfoto als Hintergrund. Sie erscheint nur, wenn heute ein Abendessen mit Rezept geplant ist.

yaml
1type: custom:mushroom-template-card
2primary: "{{ states('sensor.mealie_abendessen_heute') }}"
3secondary: >-
4  {% set t = state_attr('sensor.mealie_abendessen_heute','total_time') %}Heute Abend{{ ' · ' ~ t if t else '' }}
5icon: mdi:pot-steam
6icon_color: "#f0665b"
7multiline_secondary: false
8tap_action:
9  action: url
10  url_path: http://192.168.178.50:9000/household/mealplan/planner/view
11visibility:
12  - condition: state
13    entity: image.mealie_abendessen_foto
14    state_not: unavailable
15  - condition: state
16    entity: image.mealie_abendessen_foto
17    state_not: unknown
18grid_options:
19  columns: full
20  rows: 4
21card_mod:
22  style: |
23    ha-card {
24      height: 100%; box-sizing: border-box;
25      border: none !important; border-radius: 22px !important; overflow: hidden;
26      box-shadow: 0 6px 18px rgba(16,23,43,0.18) !important;
27      background: linear-gradient(180deg, rgba(16,23,43,0) 35%, rgba(16,23,43,0.55) 62%, rgba(16,23,43,0.92) 100%),
28        url('{{ state_attr('image.mealie_abendessen_foto','entity_picture') }}') center / cover no-repeat !important;
29      --primary-text-color: #ffffff; --secondary-text-color: rgba(255,255,255,0.88);
30      --ha-tile-info-primary-color: #ffffff; --ha-tile-info-secondary-color: rgba(255,255,255,0.88);
31      --ha-tile-info-primary-font-size: 22px; --ha-tile-info-primary-font-weight: 700;
32      --ha-tile-info-primary-line-height: 28px; --ha-tile-info-secondary-font-size: 15px;
33      --ha-tile-info-secondary-line-height: 20px;
34    }
35    .content { align-items: flex-end !important; padding: 0 16px 18px 16px !important; }
36    ha-tile-icon { --tile-icon-color: #ffffff; --tile-color: #f0665b; }
37    .background { background: transparent !important; }

Fürs Handy reichen rows: 3. Für den Abend ohne Plan zeigt eine zweite, schlichte Karte „Nichts geplant“ mit der umgekehrten Bedingung (image.mealie_abendessen_foto ist unavailable oder unknown).

Daneben passen diese beiden Karten auf das Küchen-Dashboard. Die erste zeigt den Essensplan als Wochenliste:

yaml
1type: calendar
2initial_view: listWeek
3entities:
4  - calendar.mealie_fruhstuck
5  - calendar.mealie_mittagessen
6  - calendar.mealie_abendessen
7  - calendar.mealie_nachtisch

Die zweite ist die Einkaufsliste:

yaml
type: todo-list
entity: todo.mealie_<listenname>  # z. B. todo.mealie_einkaufsliste, wenn die Liste „Einkaufsliste“ heißt

Tipps und Troubleshooting

Ein paar Stolperstellen kenne ich inzwischen. Die stehen hier nach Symptom sortiert.

Rezeptseiten im iframe bleiben unterwegs leer

Mealie läuft per http im LAN, Home Assistant über Nabu Casa per https. Der Browser blockiert dann den http-Inhalt im iframe. Das Foto auf der Karte betrifft das nicht, weil Home Assistant es selbst lädt.

Sensor bleibt auf „Nichts geplant“, obwohl etwas geplant ist

Der Sensor liest nur Einträge vom Typ Abendessen. Ist der Eintrag eine reine Notiz ohne Rezept, steht ihr Titel im Sensor. Die Fotokarte bleibt aber aus, weil es kein Rezeptbild gibt.

Fehler beim Weiterreichen des ganzen Eintrags

Die Antwort von „Essensplan abrufen“ enthält Datumsobjekte. Wer einen kompletten Eintrag in eine Variable legt, bekommt einen unlesbaren String. Deshalb zieht das Package nur einzelne Textfelder heraus.

Text sitzt nach einem Mushroom-Update falsch

Ab Mushroom v5 steuern die CSS-Variablen --ha-tile-info-* die Schrift. Die Höhe kommt aus grid_options mit rows. Feste Pixelhöhen am ha-card schneiden das Foto ab.

KI-Import bricht ab

Prüfe, ob der Anbieter als Standard- und als Bildanbieter gesetzt ist und die Basis-URL mit /v1/ endet. Ohne Bildanbieter zeigt Mealie beim Foto-Import nur den Hinweis, einen Bild-Anbieter zu konfigurieren.

Zutaten landen ohne Einheit im Rezept

Lade die Musterdaten aus Schritt 4 und füge fehlende Schreibweisen im Zutaten-Parser als Alias hinzu.

Nutzt du Mealie auch oder hast du eine andere Lösung für deine Rezepte? Schreib mir gerne, was du davon hältst.

Diskussion im Forum

Hast du Fragen oder Ideen zu diesem Thema?

Diskutiere im Forum

Video teilen

Community

Unterstütze den Kanal

Hat dir der Beitrag geholfen? Es gibt zwei Wege, etwas zurückzugeben.