VPS पर Mealie कैसे इंस्टॉल करें: Docker Compose गाइड
अपने VPS पर Mealie को Docker Compose के साथ सेटअप करना सीखें। यह गाइड आपको URL से रेसिपी इंपोर्ट करने, मील प्लान बनाने, Nginx कॉन्फ़िगरेशन और TLS सुरक्षा सेटअप करने में मदद करेगी।
Self-hosted recipe manager क्या करता है
एक self-hosted recipe manager आपकी recipes को आपके अपने सर्वर पर स्थित database में सुरक्षित रखता है, और Mealie वह विकल्प है जिसे अधिकांश घरों में पसंद किया जाता है। आप किसी recipe पेज का URL पेस्ट करते हैं और Mealie उसमें से सामग्री (ingredients), चरण (steps), मात्रा (yield) और पकाने का समय (cook time) निकाल लेता है, जबकि अनावश्यक विवरण और विज्ञापनों को हटा देता है। आपके संग्रह में केवल भोजन से संबंधित जानकारी ही बचती है।
ऐप का बाकी हिस्सा काफी सरल है। इसमें एक साप्ताहिक meal plan है जिसमें आप recipes को drag कर सकते हैं, और उस plan के आधार पर एक shopping list तैयार हो जाती है। खाना बनाने वाले प्रत्येक व्यक्ति का अपना अलग login होता है। यह सब एक ही container में चलता है और requests के बीच idle रहता है, इसलिए एक साधारण VPS पर भी यह बिना किसी लोड के चलता है।
यह गाइड Docker Compose का उपयोग करती है। यदि services: और volumes: शब्द आपके लिए नए हैं, तो पहले Docker Compose files कैसे बनाई जाती हैं पढ़ें, क्योंकि नीचे दी गई पूरी प्रक्रिया एक compose file और चार commands पर आधारित है।
Docker Compose के साथ Mealie इंस्टॉल करें
Mealie अपनी images को GitHub container registry पर publish करता है। जुलाई 2026 तक, वर्तमान stable tag v3.22.0 है। latest का उपयोग करने के बजाय एक version को pin करें: latest के साथ, किसी भी दिन होने वाला docker compose pull आपको ऐसे database migration पर ले जा सकता है जिसके लिए आप तैयार नहीं थे।
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:इसे शुरू करने से पहले दो पंक्तियों पर ध्यान देना आवश्यक है।
Port को 127.0.0.1:9925:9000 के रूप में लिखा गया है, न कि 9925:9000 के रूप में। Container अंदर 9000 port पर listen करता है, और host इसे 9925 पर map करता है। उस map को loopback address पर bind करने का अर्थ है कि Nginx, Mealie तक पहुँच सकता है, लेकिन internet नहीं। Docker packet filter में अपने स्वयं के नियम लिखता है, इसलिए एक साधारण 9925:9000 बाहर से तब भी पहुँच योग्य होता है जब आपका firewall कहता है कि port बंद है। यह आश्चर्य एक बार समझने योग्य है: देखें Docker द्वारा publish किए गए ports ufw को क्यों अनदेखा करते हैं।
BASE_URL वह सटीक public address होना चाहिए जिसका आप उपयोग करेंगे, जिसमें scheme शामिल हो और अंत में कोई slash न हो। Mealie इससे password reset links और invitation links बनाता है। यदि आप इसे http://localhost:9925 पर set करते हैं, तो आपके द्वारा अपने partner को भेजा गया invitation एक ऐसा link होगा जो केवल server पर ही काम करेगा।
इसे शुरू करें और पहली boot प्रक्रिया को देखें।
sudo docker compose up -d
sudo docker compose logs -f mealieपहली बार शुरू करने पर SQLite database बनता है और migrations चलते हैं, जिसमें कुछ सेकंड लगते हैं। जब log स्थिर हो जाए और migration lines प्रिंट करना बंद कर दे, तो app को स्थानीय रूप से जाँचे।
curl -I http://127.0.0.1:9925200 OK का अर्थ है कि app चल रहा है। Connection refused का अर्थ है कि container नहीं चल रहा है: sudo docker compose ps चलाएँ और exit code पढ़ें। जो container code 137 के साथ बंद हुआ, उसे 1000M memory limit पार करने के कारण kill कर दिया गया था, जो सबसे छोटे plans पर होता है।
पहली बार लॉगिन करना और ओपन साइनअप बंद करना
डिफ़ॉल्ट अकाउंट changeme@example.com है और इसका पासवर्ड MyPassword है। इससे लॉगिन करें, और तुरंत दोनों को बदल दें, क्योंकि यह जोड़ा डॉक्यूमेंटेशन में दिया गया है और इसलिए हर स्कैनर की पहुँच में है।
कंपोज़ फ़ाइल में ALLOW_SIGNUP: "false" जानबूझकर रखा गया है। यदि साइनअप खुला है, तो कोई भी व्यक्ति जिसे आपका पता मिल जाए, वह आपके रेसिपी बॉक्स में अकाउंट बना सकता है। इसे बंद करने पर, आप एडमिन एरिया से लोगों को जोड़ते हैं, जो एक इनविटेशन लिंक बनाता है जिसे आप स्वयं उन्हें भेजते हैं। वह लिंक BASE_URL से बनता है, इसीलिए यह वैल्यू महत्वपूर्ण है। यदि आप एक ही सर्वर पर कई ऐप्स चला रहे हैं और उन सभी के लिए एक ही पासवर्ड चाहते हैं, तो Mealie अपने लॉगिन को किसी बाहरी आइडेंटिटी प्रोवाइडर जैसे कि सेल्फ-होस्टेड Authentik इंस्टेंस को सौंप सकता है।
Mealie उपयोगकर्ताओं को एक हाउसहोल्ड में समूहित करता है। एक हाउसहोल्ड के सभी सदस्य रेसिपी कलेक्शन, मील प्लान और शॉपिंग लिस्ट साझा करते हैं, जो कि एक परिवार की आवश्यकता होती है। एक ही सर्वर पर अलग-अलग हाउसहोल्ड अलग-अलग कलेक्शन रखते हैं, जो कि फ्लैटशेयर के लिए उपयुक्त है जहाँ लोग एंकोवीज़ (anchovies) जैसी चीज़ों पर सहमत नहीं होते।
इम्पोर्टर, जिसे चलाने का मुख्य कारण
रेसिपी कलेक्शन खोलें, URL से रेसिपी बनाने का विकल्प चुनें और लिंक पेस्ट करें। Mealie पेज को फेच करता है और स्ट्रक्चर्ड रेसिपी डेटा की तलाश करता है, जो कि वह मशीन-रीडेबल ब्लॉक है जिसे अधिकांश रेसिपी साइटें सर्च इंजन के लिए एम्बेड करती हैं। जब वह ब्लॉक मौजूद होता है, तो इम्पोर्ट साफ और तुरंत हो जाता है।
आप किसी इमेज या पेस्ट किए गए प्लेन टेक्स्ट से भी इम्पोर्ट कर सकते हैं, जो कि कुकबुक के किसी पेज की फोटो के लिए उपयोगी है। वे एक धीमी प्रक्रिया से गुजरते हैं और बाद में जांच की मांग करते हैं, क्योंकि हाथ से लिखे गए भिन्नों (fractions) को गलत पढ़ना आसान होता है।
बल्क इम्पोर्ट उसी स्क्रीन से चलते हैं: पतों की एक सूची पेस्ट करें, प्रति लाइन एक, और Mealie बैकग्राउंड में उन पर काम करता है। दो सौ बुकमार्क का कलेक्शन एक बार में ही ट्रांसफर हो जाता है।
Meal plans और shopping list
Meal planner एक कैलेंडर है। किसी recipe को खींचकर (drag करके) किसी दिन पर रखें, और वह plan हो जाएगी। इसके बाद shopping list planned recipes की सामग्री को एक सूची में इकट्ठा करती है और समान वस्तुओं को जोड़ देती है, ताकि यदि दो recipes में प्याज की आवश्यकता हो, तो दो लाइनों के बजाय एक ही लाइन दिखाई दे।
दुकान पर रहते समय यह सूची आपके फोन पर एक live page के रूप में काम करती है। चूंकि यह आपके अपने server पर होती है, इसलिए घर का हर सदस्य एक ही समय पर एक ही सूची देख सकता है, और यदि एक व्यक्ति milk को tick करके हटाता है, तो वह दूसरे व्यक्ति की screen से भी हट जाता है।
Nginx और TLS को सामने रखें
Mealie केवल plain HTTP का उपयोग करता है और इसमें स्वयं का कोई certificate handling नहीं है। इसके सामने nginx में transport layer security (TLS) को terminate करें। सबसे पहले अपने सर्वर पर एक DNS A record point करें, क्योंकि certificate step उस नाम को verify करता है।
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 को print करना और syntax is ok तथा test is successful का उपयोग करना ही मुख्य द्वार है। केवल तभी reload करें जब यह पास हो जाए, क्योंकि एक खराब config को reload करने पर पुरानी config ही चलती रहती है और अगली restart तक गलती का पता नहीं चलता।
client_max_body_size 64M यहाँ इसलिए है क्योंकि nginx का default मान 1 MB है। browser के माध्यम से recipe की photo upload करने या backup restore करने पर इससे बड़ी body भेजी जाती है, और इस line के बिना आपको nginx से 413 Request Entity Too Large error मिलता है, न कि Mealie से, इसलिए application log में कुछ भी दिखाई नहीं देता।
इसके बाद certificate जारी करें। उस step और उसके renewal timer के बारे में certbot के साथ nginx के लिए Let's Encrypt certificate जारी करना में बताया गया है।
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d recipes.example.comCertbot server block को 443 पर listen करने के लिए rewrite करता है और port 80 से एक redirect जोड़ता है। साइट को https:// पर load करें और पुष्टि करें कि browser certificate को स्वीकार करता है। यदि Mealie load हो जाता है लेकिन उसके links आपको http:// पर भेजते हैं, तो इसका मतलब है कि BASE_URL में अभी भी http लिखा है जिसे ठीक करने की आवश्यकता है, जिसके बाद नए value के साथ container को फिर से बनाने के लिए sudo docker compose up -d का उपयोग करें।
Mealie को example.com/recipes जैसे subpath के अंतर्गत serve करना काम नहीं करता है, क्योंकि frontend को subpath से serve नहीं किया जा सकता है। एक subdomain का उपयोग करें।
Backups, और restore वास्तव में क्या करता है
Mealie का सारा डेटा container के अंदर /app/data/ में रहता है, जो कि mealie-data volume है। उस volume की प्रतिलिपि बनाने का अर्थ है कि आपने recipes, images और database को एक साथ copy कर लिया है।
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 mealieVolume के नाम में project का नाम prefix के रूप में जुड़ा होता है, और project का नाम वह directory है जिसमें compose file स्थित है। /srv/mealie से volume का नाम mealie_mealie-data होता है, इसीलिए पहली command docker volume ls है: जो नाम यह print करे, उसी का उपयोग करें, न कि इस guide में दिए गए नाम का। Container को पहले रोकना महत्वपूर्ण है, क्योंकि SQLite अक्सर write process के बीच में होता है, जिससे live copy restore करने पर unreadable हो सकती है।
Mealie के admin area में अपना एक backup page भी है, जो database को JSON के रूप में आपकी images के साथ एक portable archive में लिखता है। servers के बीच migration के लिए इसका उपयोग करें, क्योंकि यह version change के दौरान भी सुरक्षित रहता है, जबकि raw file copy में ऐसा नहीं हो सकता। एक archive को restore करना जानबूझकर विनाशकारी (destructive) बनाया गया है: यह archive load करने से पहले वर्तमान database को delete कर देता है, और इसे undo नहीं किया जा सकता। प्रक्रिया पूरी होने पर आप log out हो जाएंगे।
जब तक copy उसी server पर मौजूद है, तब तक वह backup नहीं है। archive को एक schedule के अनुसार कहीं और भेजें, जिसके लिए restic के साथ encrypted off-server backups का उपयोग किया जाता है।
Mealie को अपडेट करना
cd /srv/mealie
sudo nano docker-compose.yml
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs -f mealieफाइल में पिन किए गए version को बढ़ाएं, फिर pull करें और container को recreate करें। नए image के पहली बार start होने पर migrations अपने आप चलते हैं। major version change से पहले volume की एक copy जरूर लें, क्योंकि यदि migration बीच में विफल हो जाता है, तो database ऐसी स्थिति में आ सकता है जिसे पिछला image open नहीं कर पाएगा। अपने वर्तमान version और नए version के बीच के सभी release notes को ध्यान से पढ़ें।
जब इम्पोर्टर विफल हो जाता है
कुछ साइटें कोई भी स्ट्रक्चर्ड रेसिपी डेटा पब्लिश नहीं करती हैं, और ऐसी स्थिति में Mealie खाली सामग्री सूची (ingredient list) के साथ केवल टाइटल इम्पोर्ट करता है। इसे आप किसी कॉन्फ़िगरेशन से ठीक नहीं कर सकते। इसके बजाय रेसिपी टेक्स्ट को मैन्युअल रूप से पेस्ट करें।
अन्य विफलताएं रेसिपी साइट के सामने मौजूद बॉट प्रोटेक्शन के कारण होती हैं, जो Mealie को रेसिपी के बजाय एक चैलेंज पेज भेजती हैं। Mealie पहले से ही ब्राउज़र का रूप धारण करता है और इसे कम करने के लिए अपने user agent को रोटेट करता है। जब कोई साइट फिर भी मना कर दे, तो दस्तावेज़ों में दिए गए विकल्प यह हैं कि स्क्रैपर को बेहतर एड्रेस रेपुटेशन वाले प्रॉक्सी के माध्यम से भेजें, या एक FlareSolverr इंस्टेंस चलाएं जो वास्तविक ब्राउज़र में चैलेंज को हल करता है। ये दोनों विकल्प वैकल्पिक हैं, और दोनों को कंटेनर पर environment variables के माध्यम से सेट किया जाता है।
यदि इम्पोर्ट इसलिए विफल होता है क्योंकि आपका सर्वर साइट तक पहुँच ही नहीं पा रहा है, तो यह एक अलग समस्या है। स्क्रैपर को दोष देने से पहले, बॉक्स से curl -I https://the-site.example/recipe के साथ इसका परीक्षण करें और स्टेटस लाइन को पढ़ें।
यह कहाँ फिट बैठता है
Mealie एक परिवार के लिए self-hosted application के रूप में शुरुआत करने के लिए एक अच्छा विकल्प है, क्योंकि आपके साथ रहने वाले लोग बिना कहे ही इसका उपयोग करेंगे। यह काम Immich के साथ अपनी खुद की फोटो लाइब्रेरी चलाने जैसा ही है, हालांकि यह काफी हल्का है, और यह इस वर्ष self-host करने योग्य चीजों की व्यापक सूची में आता है। एक छोटा सर्वर इन दोनों को संभाल सकता है। उस दूसरे काम के लिए Immich ही एकमात्र विकल्प नहीं है, और यदि आप अभी भी निर्णय ले रहे हैं, तो PhotoPrism और Immich की memory requirements और backup commands में इतना अंतर है कि बाकी डिस्क स्पेस देने से पहले उन्हें पढ़ लेना उचित है।
FAQ
रेसिपी URL इम्पोर्ट करने में विफलता क्यों होती है?
इसके दो सामान्य कारण हैं। या तो पेज पर कोई स्ट्रक्चर्ड रेसिपी डेटा प्रकाशित नहीं है, इसलिए स्क्रैपर को कुछ नहीं मिलता और आपको बिना सामग्री (ingredients) वाला शीर्षक मिलता है, या साइट के सामने मौजूद बॉट-प्रोटेक्शन लेयर रेसिपी के बजाय एक चैलेंज पेज दिखाती है। दूसरे मामले के लिए, Mealie को बेहतर एड्रेस रेपुटेशन वाले प्रॉक्सी पर, या किसी self-hosted FlareSolverr इंस्टेंस पर पॉइंट किया जा सकता है जो वास्तविक ब्राउज़र में चैलेंज को हल करता है। कुछ भी बदलने से पहले पुष्टि करें कि आपका सर्वर curl -I के साथ उस पेज तक पहुँच सकता है।
क्या मुझे PostgreSQL की आवश्यकता है, या SQLite पर्याप्त है?
घरेलू उपयोग के लिए SQLite पर्याप्त है और यह डिफ़ॉल्ट है। जब डेटा डायरेक्टरी नेटवर्क अटैच्ड स्टोरेज (NAS) पर हो, तब PostgreSQL पर स्विच करें, क्योंकि नेटवर्क फाइलसिस्टम पर SQLite का उपयोग करने से locked-database त्रुटियाँ आती हैं और फ़ाइल करप्ट हो सकती है। PostgreSQL के तहत रिस्टोर करने के लिए डेटाबेस यूजर का सुपरयूज़र होना आवश्यक है, क्योंकि रिस्टोर प्रक्रिया आर्काइव लोड करने से पहले सब कुछ डिलीट कर देती है।
क्या मैं बिना डोमेन नाम के Mealie चला सकता हूँ?
हाँ, अपने नेटवर्क पर। BASE_URL को उस पते पर सेट करें जिसे आप वास्तव में टाइप करेंगे, जैसे कि http://192.168.1.20:9925, और nginx को छोड़ दें। इनविटेशन और पासवर्ड रीसेट लिंक BASE_URL से बनाए जाते हैं, इसलिए गलत मान होने पर ऐसे लिंक बनेंगे जिन्हें कोई और नहीं खोल पाएगा। इसे प्लेन HTTP पर इंटरनेट पर एक्सपोज़ न करें, क्योंकि ऐसा करने पर लॉगिन विवरण स्पष्ट रूप से (in the clear) भेजे जाते हैं।
मैं अपने परिवार के सदस्यों को उनके अपने लॉगिन कैसे दूँ?
ALLOW_SIGNUP को "false" पर सेट रहने दें और एडमिन एरिया से लोगों को जोड़ें, जिससे एक इनविटेशन लिंक बनेगा जिसे आप उन्हें भेज सकते हैं। जो लोग एक ही किचन शेयर करते हैं, उन्हें एक ही हाउसहोल्ड में रखें ताकि वे रेसिपी, मील प्लान और शॉपिंग लिस्ट शेयर कर सकें। एक सर्वर पर अलग-अलग हाउसहोल्ड रखने से उनके कलेक्शन अलग-अलग रहते हैं।
यदि मैं Mealie चलाना बंद कर दूँ तो मेरी रेसिपी का क्या होगा?
वे सुरक्षित रहती हैं। एडमिन बैकअप आपके डेटा को JSON के रूप में लिखता है, और Mealie रेसिपी को प्लेन markdown फ़ाइलों के रूप में भी एक्सपोर्ट कर सकता है, जो किसी भी सॉफ़्टवेयर के बिना किसी भी टेक्स्ट एडिटर में पढ़ी जा सकती हैं। आवश्यकता पड़ने से पहले एक एक्सपोर्ट लें और जाँच लें कि आप इसे खोल पा रहे हैं।