Mealie installeren op een VPS met Docker Compose
Host uw eigen receptenbeheerder met Mealie op een VPS. Leer hoe u Docker Compose gebruikt voor een veilige installatie met Nginx, TLS-encryptie en automatische back-ups.
Wat een zelfgehoste receptenbeheerder doet
Een zelfgehoste receptenbeheerder slaat uw recepten op in een database op een server die u zelf beheert, en Mealie is de keuze waar de meeste huishoudens op uitkomen. U plakt het adres van een receptenpagina en Mealie leest de ingrediënten, de stappen, de opbrengst en de bereidingstijd eruit, terwijl het de verhalen en advertenties weglaat. Wat in uw verzameling terechtkomt, is het eten zelf.
De rest van de applicatie is compact. Er is een wekelijkse maaltijdplanner waar u recepten naartoe sleept, en een boodschappenlijst die op basis van dat plan wordt samengesteld. Elke persoon die kookt krijgt een eigen inlogaccount. Alles draait in één container en verbruikt nauwelijks resources tussen verzoeken door, waardoor een bescheiden VPS de applicatie moeiteloos draait.
Deze handleiding maakt gebruik van Docker Compose. Als de termen services: en volumes: nieuw voor u zijn, lees dan eerst hoe Docker Compose-bestanden zijn opgebouwd, aangezien alles hieronder één compose-bestand en vier commando's beslaat.
Mealie installeren met Docker Compose
Mealie publiceert zijn images naar de GitHub container registry. Sinds juli 2026 is de huidige stabiele tag v3.22.0. Pin een versie in plaats van latest te gebruiken: met latest kan een docker compose pull op een willekeurige dag leiden tot een databasemigratie waar u nog niet klaar voor bent.
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:Twee regels verdienen aandacht voordat u het start.
De poort is geschreven als 127.0.0.1:9925:9000 en niet als 9925:9000. De container luistert intern op 9000 en de host mapt 9925 hiernaartoe. Door deze mapping aan het loopback-adres te binden, kan Nginx Mealie bereiken, maar het internet niet. Docker schrijft zijn eigen regels in de packet filter, waardoor een simpele 9925:9000 van buitenaf bereikbaar is, zelfs als uw firewall aangeeft dat de poort gesloten is. Het is nuttig om deze verrassing eenmaal te begrijpen: zie waarom gepubliceerde Docker-poorten ufw negeren.
BASE_URL moet het exacte publieke adres zijn dat u gaat gebruiken, inclusief het schema en zonder afsluitende slash. Mealie bouwt wachtwoordherstel- en uitnodigingslinks op basis hiervan. Stelt u dit in op http://localhost:9925, dan zal de uitnodiging die u naar uw partner stuurt een link bevatten die alleen op de server zelf werkt.
Start het en bekijk de eerste opstartfase.
sudo docker compose up -d
sudo docker compose logs -f mealieDe eerste start creëert de SQLite-database en voert de migraties uit, wat enkele seconden duurt. Wanneer de log tot rust komt en stopt met het tonen van migratieregels, controleer de applicatie dan lokaal.
curl -I http://127.0.0.1:9925Een 200 OK betekent dat de applicatie actief is. Connection refused betekent dat de container niet draait: voer sudo docker compose ps uit en lees de exitcode. Een container die stopte met code 137 werd beëindigd omdat de geheugenlimiet van 1000M werd overschreden, wat voorkomt bij de kleinste abonnementen.
Eerste aanmelding en het uitschakelen van open registratie
Het standaardaccount is changeme@example.com met het wachtwoord MyPassword. Meld u hiermee aan en wijzig beide direct, aangezien dit paar in de documentatie staat en daarom in elke scanner voorkomt.
ALLOW_SIGNUP: "false" in het compose-bestand is een bewuste keuze. Met open registratie kan iedereen die het adres vindt een account aanmaken in uw receptenbox. Wanneer dit is uitgeschakeld, voegt u zelf personen toe vanuit het beheerderspaneel, wat een uitnodigingslink genereert die u zelf verstuurt. Die link wordt opgebouwd op basis van BASE_URL, en daarom is de waarde ervan van belang. Als u uiteindelijk meerdere applicaties op dezelfde server draait en voor alle applicaties hetzelfde wachtwoord wilt gebruiken, kan Mealie de aanmelding overdragen aan een externe identiteitsprovider, zoals een zelfgehoste Authentik-instantie.
Mealie groepeert gebruikers in een huishouden. Iedereen in hetzelfde huishouden deelt de receptenverzameling, de maaltijdplanning en de boodschappenlijst; dit is wat een gezin doorgaans wenst. Aparte huishoudens op dezelfde server behouden gescheiden verzamelingen, wat ideaal is voor een woongroep waar meningen over ansjovis uiteenlopen.
De importfunctie, de reden om dit te draaien
Open de receptencollectie, kies voor het aanmaken van een recept vanaf een URL en plak een link. Mealie haalt de pagina op en zoekt naar gestructureerde receptgegevens; het machineleesbare blok dat de meeste receptensites insluiten voor zoekmachines. Wanneer dit blok aanwezig is, verloopt de import schoon en direct.
U kunt ook importeren vanaf een afbeelding of vanuit platte tekst die u plakt, wat handig is voor een foto van een pagina uit een kookboek. Deze doorlopen een trager proces en vereisen achteraf controle, aangezien een handgeschreven breuk gemakkelijk verkeerd kan worden gelezen.
Bulk-imports worden vanaf hetzelfde scherm uitgevoerd: plak een lijst met adressen, één per regel, en Mealie verwerkt deze op de achtergrond. Een verzameling van tweehonderd bladwijzers wordt in één sessie overgezet.
Maaltijdplanning en de boodschappenlijst
De maaltijdplanner is een kalender. Sleep een recept naar een dag om het in te plannen. De boodschappenlijst verzamelt vervolgens de ingrediënten van de geplande recepten in één overzicht en combineert dubbele items; als twee recepten uien vereisen, verschijnt er één regel in plaats van twee.
De lijst is een actieve pagina die u in de winkel op uw telefoon kunt raadplegen. Omdat de lijst op uw eigen server staat, ziet iedereen in het huishouden tegelijkertijd dezelfde lijst. Wanneer één persoon melk afvinkt, verdwijnt dit item direct van het scherm van de andere persoon.
Plaats nginx en TLS voor de applicatie
Mealie communiceert via standaard HTTP en beschikt niet over eigen certificaatbeheer. Beëindig de transport layer security (TLS) daarom in nginx vóór de applicatie. Wijs eerst een DNS A-record naar uw server, aangezien de certificaatstap deze naam verifieert.
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 printen van syntax is ok en test is successful fungeert als controle. Voer pas een reload uit nadat deze controle slaagt, omdat het herladen van een defecte configuratie de oude configuratie actief laat en de fout verbergt tot de volgende herstart.
client_max_body_size 64M is noodzakelijk omdat de standaardwaarde van nginx 1 MB is. Het uploaden van een receptfoto of het herstellen van een back-up via de browser verstuurt een groter bestand; zonder deze regel ontvangt u een 413 Request Entity Too Large van nginx, niet van Mealie, waardoor het applicatielogboek geen informatie bevat.
Vraag vervolgens het certificaat aan. Deze stap en de bijbehorende timer voor vernieuwing worden behandeld in het uitgeven van een Let's Encrypt certificaat voor nginx met certbot.
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d recipes.example.comCertbot herschrijft het serverblok om te luisteren op poort 443 en voegt een redirect toe vanaf poort 80. Laad de site via https:// en bevestig dat de browser het certificaat accepteert. Als Mealie laadt, maar de interne links verwijzen naar http://, dan bevat BASE_URL nog steeds http en moet dit worden gecorrigeerd, gevolgd door sudo docker compose up -d om de container met de nieuwe waarde opnieuw aan te maken.
Het aanbieden van Mealie via een subpad zoals example.com/recipes werkt niet, omdat de frontend niet vanaf een subpad kan worden geserveerd. Gebruik een subdomein.
Backups en wat een restore daadwerkelijk doet
Alles wat Mealie bezit, bevindt zich in /app/data/ binnen de container; dit is het mealie-data volume. Kopieer dat volume en u heeft de recepten, de afbeeldingen en de database in één keer gekopieerd.
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 mealieDe volumenaam bevat de projectnaam als voorvoegsel, en de projectnaam is de map waarin het compose-bestand staat. Op basis van /srv/mealie is het volume mealie_mealie-data; daarom is het eerste commando docker volume ls: gebruik de naam die wordt weergegeven, niet de naam in deze handleiding. Het is belangrijk om de container eerst te stoppen, omdat SQLite vaak midden in een schrijfactie zit, waardoor een live-kopie onleesbaar kan zijn bij het terugzetten.
Mealie heeft ook een eigen backuppagina in het beheerdersgedeelte. Deze schrijft een draagbaar archief dat de database als JSON bevat, samen met uw afbeeldingen. Gebruik dit voor het verplaatsen tussen servers, aangezien dit een versie-overgang overleeft die een directe bestandskopie mogelijk niet overleeft. Het terugzetten van een dergelijk archief is ontworpen als een destructieve actie: het verwijdert de huidige database voordat het archief wordt geladen, en dit kan niet ongedaan worden gemaakt. U wordt uitgelogd zodra het proces is voltooid.
Geen van beide kopieën is een backup zolang deze op dezelfde server staat. Verplaats het archief volgens een schema naar een andere locatie; dit is waar versleutelde off-server backups met restic voor bedoeld is.
Mealie bijwerken
cd /srv/mealie
sudo nano docker-compose.yml
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mealieVerhoog de vastgezette versie in het bestand, haal vervolgens de nieuwe image op en maak de container opnieuw aan. Migraties worden uitgevoerd bij de eerste start van de nieuwe image. Maak een kopie van het volume voordat u een grote versie-update doorvoert, omdat een mislukte migratie een database achterlaat die de vorige image niet meer kan openen. Lees de release notes voor alle versies tussen uw huidige versie en de nieuwe versie.
Wanneer de importeur faalt
Sommige websites publiceren helemaal geen gestructureerde receptgegevens. Mealie importeert in dat geval een titel met een lege ingrediëntenlijst. Dit is niet via configuratie op te lossen. Voer de recepttekst in dat geval handmatig in.
Andere fouten ontstaan door bot-beveiliging voor de receptenwebsite. Deze reageert op Mealie met een uitdagingspagina in plaats van met het recept. Mealie imiteert al een browser en roteert de user agent om dit te beperken. Wanneer een site de toegang blijft weigeren, zijn de gedocumenteerde opties om de scraper via een proxy met een betere reputatie te sturen, of een FlareSolverr-instantie te draaien die de uitdaging in een echte browser oplost. Beide zijn optioneel en worden ingesteld via omgevingsvariabelen op de container.
Een import die faalt omdat uw server de site helemaal niet kan bereiken, is een ander probleem. Test dit vanaf de server met curl -I https://the-site.example/recipe en lees de statusregel voordat u de scraper de schuld geeft.
Waar het past
Mealie is een geschikte eerste zelfgehoste applicatie voor een huishouden, omdat uw huisgenoten het zonder aansporing zullen gebruiken. Het beheer ervan is vergelijkbaar met het draaien van uw eigen fotobibliotheek met Immich, hoewel het veel lichter is. Het maakt deel uit van de bredere lijst met dingen die het waard zijn om dit jaar zelf te hosten. Eén kleine server kan beide aan. Immich is niet de enige kandidaat voor die tweede taak. Als u nog aan het beslissen bent, verschillen de geheugenvereisten en back-upcommando's van PhotoPrism en Immich voldoende om ze te lezen voordat u de rest van de schijfruimte toewijst.
FAQ
Waarom mislukt het importeren van een recept-URL?
Er zijn twee veelvoorkomende oorzaken. Of de pagina publiceert geen gestructureerde receptgegevens, waardoor de scraper niets vindt en u een titel zonder ingrediënten krijgt, of een bot-beveiligingslaag voor de site retourneert een uitdagingspagina in plaats van het recept. Voor het tweede geval kan Mealie worden gekoppeld aan een proxy met een betere reputatie, of aan een zelfgehoste FlareSolverr-instantie die de uitdaging in een echte browser oplost. Bevestig eerst dat uw server de pagina überhaupt kan bereiken met curl -I voordat u iets wijzigt.
Heb ik PostgreSQL nodig, of is SQLite voldoende?
SQLite is voldoende voor huishoudelijk gebruik en is de standaardinstelling. Stap over naar PostgreSQL wanneer de datamap zich op netwerkopslag (NAS) bevindt, omdat SQLite via een netwerkbestandssysteem fouten geeft over een vergrendelde database en het bestand kan beschadigen. Herstelacties onder PostgreSQL vereisen dat de databasegebruiker een superuser is, aangezien het herstelproces alles verwijdert voordat het archief wordt geladen.
Kan ik Mealie draaien zonder domeinnaam?
Ja, binnen uw eigen netwerk. Stel BASE_URL in op het adres dat u daadwerkelijk zult typen, zoals http://192.168.1.20:9925, en sla nginx over. Uitnodigings- en wachtwoordherstellinks worden gegenereerd op basis van BASE_URL; een onjuiste waarde zorgt voor links die niemand anders kan openen. Stel het niet bloot aan het internet via onversleuteld HTTP, omdat de inloggegevens dan in leesbare tekst worden verzonden.
Hoe geef ik mijn familie hun eigen inloggegevens?
Laat ALLOW_SIGNUP ingesteld op "false" en voeg mensen toe vanuit het beheerderspaneel; dit genereert een uitnodigingslink die u naar hen kunt sturen. Plaats iedereen die een keuken deelt in hetzelfde huishouden, zodat zij de recepten, de maaltijdplanning en de boodschappenlijst delen. Aparte huishoudens op één server behouden gescheiden collecties.
Wat gebeurt er met mijn recepten als ik stop met het draaien van Mealie?
Deze blijven beschikbaar. De beheer-back-up schrijft uw gegevens als JSON, en Mealie kan recepten ook exporteren als eenvoudige markdown-bestanden. Deze blijven leesbaar in elke teksteditor zonder dat er extra software nodig is. Maak één export voordat u deze nodig heeft en controleer of u deze kunt openen.