Immich का बैकअप और रिस्टोर कैसे करें: पूरी गाइड
Immich बैकअप के लिए Postgres SQL डंप और originals फोल्डर का सही उपयोग जानें। Postgres डेटा डायरेक्टरी कॉपी करने की गलती से बचें और रिस्टोर के दौरान खाली टाइमलाइन की समस्या को दूर करें।
Immich बैकअप में क्या शामिल होना चाहिए
Immich बैकअप तीन चीजों का एक साथ लिया गया संग्रह है। UPLOAD_LOCATION के अंतर्गत मौजूद originals, Postgres डेटाबेस का एक SQL डंप, और वे .env तथा docker-compose.yml जो स्टैक का विवरण देते हैं। रिस्टोर करने का अर्थ है Immich सर्वर को रोककर उस डंप को एक नए डेटाबेस में डालना और उसके बाद ही बाकी स्टैक को शुरू करना। यदि आप क्रम गलत करते हैं, तो आपको एक ऐसा Immich मिलेगा जो पूरी डिस्क होने के बावजूद खाली टाइमलाइन दिखाएगा।
यह विभाजन महत्वपूर्ण है क्योंकि Immich अपनी स्थिति को दो ऐसी जगहों पर रखता है जो एक-दूसरे के बारे में कुछ नहीं जानतीं। Postgres में हर एल्बम, हर फेस क्लस्टर, हर शेयर किया गया लिंक, हर यूजर अकाउंट, API की (key) और प्रत्येक एसेट का स्टोर्ड पाथ होता है। फाइलसिस्टम में पिक्सल होते हैं। यदि आप डेटाबेस के बिना फाइलें रिस्टोर करते हैं, तो Immich आपको कुछ नहीं दिखाएगा। यदि आप फाइलों के बिना डेटाबेस रिस्टोर करते हैं, तो हर एसेट एक टूटी हुई इमेज के रूप में खुलेगी।
यहाँ दी गई कमांड्स Immich v3.1.0 के लिए लिखी गई हैं, जो अगस्त 2026 की शुरुआत में वर्तमान रिलीज है। यह प्रोजेक्ट तेजी से अपडेट होता है और प्रलेखित बैकअप प्रक्रिया एक से अधिक बार बदल चुकी है, इसलिए कुछ भी कॉपी करने से पहले उस वर्जन की जांच करें जिसे आप वास्तव में चला रहे हैं। यदि स्टैक अभी तक तैयार नहीं है, तो Immich इंस्टॉलेशन गाइड से शुरुआत करें और फिर वापस आएं।
जानें कि आपके paths कहाँ point करते हैं
.env में मौजूद दो variables इस पेज पर सब कुछ निर्धारित करते हैं। UPLOAD_LOCATION वह parent directory है जिसमें Immich सभी media files लिखता है। DB_DATA_LOCATION Postgres data directory है।
स्टॉक example.env में UPLOAD_LOCATION=./library सेट होता है, जो एक भ्रमित करने वाला default है, क्योंकि Immich इसके अंदर library नाम का एक folder बना देता है। आपकी originals फाइलें ./library/library पर जाकर सेव होती हैं। इसके बजाय एक absolute path सेट करें, ताकि backup script कभी भी इस बात पर निर्भर न रहे कि आपने उसे किस directory से run किया है।
UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0UPLOAD_LOCATION के अंदर Immich कई folders बनाता है। उनमें से तीन में ऐसा data होता है जिसे कोई भी job दोबारा नहीं बना सकती:
library: originals, जो आपके storage template के अनुसार व्यवस्थित होती हैंupload: वे originals जो अभी तक template layout में move नहीं हुई हैं, साथ ही process में चल रहे uploadsprofile: user profile pictures
यदि library खो जाता है, तो photo भी हमेशा के लिए चली जाएगी। Immich कहीं भी original की दूसरी copy नहीं रखता है।
Postgres data directory को कॉपी करना बैकअप क्यों नहीं है
DB_DATA_LOCATION एक आसान लक्ष्य की तरह दिखता है। यह एक directory है, rsync इसे कॉपी कर देगा, और कॉपी बिना किसी error के पूरी हो जाएगी। फिर भी यह बैकअप नहीं है, इसके दो कारण हैं जिन्हें आप विफल होते देख सकते हैं।
पहला कारण है tearing। Postgres हर बदलाव को पहले write-ahead log (WAL) में लिखता है, और फिर बाद में checkpoint पर उसे table files में apply करता है। इसलिए किसी भी क्षण disk पर मौजूद files बीच की स्थिति में होती हैं, और चार मिनट तक चलने वाली एक rolling copy पहली file को 02:00 बजे और आखिरी को 02:04 बजे पढ़ती है। वे दोनों files एक ही transaction का हिस्सा नहीं होतीं। जब आप उस परिणाम पर Postgres start करते हैं, तो या तो वह startup पर PANIC: could not locate a valid checkpoint record के साथ मना कर देता है, या फिर वह start तो हो जाता है लेकिन damaged page को पहली बार पढ़ते ही invalid page in block 1234 of relation base/16384/... के साथ crash हो जाता है। उस कॉपी से कुछ भी recover नहीं किया जा सकता।
दूसरा कारण तब भी बना रहता है यदि आप पहले सब कुछ stop कर दें। एक Postgres data directory उन exact binaries से बंधी होती है जिन्होंने उसे लिखा है। Immich अपने database image को digest द्वारा pin करता है, जो वर्तमान में ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 है। यह Postgres 14 है जिसमें दो vector-search extensions compile किए गए हैं। उस build द्वारा लिखी गई data directory किसी अलग Postgres major version के तहत नहीं खुलेगी, और यह अलग extension versions वाले build के तहत भी नहीं खुलेगी। आपके restore host को उस image को बिल्कुल वैसा ही reproduce करना होगा। SQL dump को इससे कोई फर्क नहीं पड़ता: वह text है, और कोई भी compatible server उसे replay कर सकता है।
pg_dump tearing की समस्या को पूरी तरह से टाल देता है। यह पूरे database को एक ही MVCC (multi-version concurrency control) snapshot के भीतर पढ़ता है, इसलिए यह database को बिल्कुल उसी स्थिति में देखता है जैसी वह एक क्षण में थी, जबकि अन्य writes उसके साथ-साथ चलते रहते हैं। यही कारण है कि इसे dump करने के लिए आपको Postgres को stop करने की आवश्यकता नहीं होती।
बैकअप से आप क्या छोड़ सकते हैं
ये फाइलें दोबारा बन जाती हैं, इसलिए आप इन्हें छोड़ सकते हैं:
thumbs: प्रीव्यू और थंबनेल इमेजencoded-video: ट्रांसकोड किए गए वीडियोDB_DATA_LOCATION: डंप से दोबारा बनाए जा सकते हैंmodel-cacheDocker वॉल्यूम: मशीन लर्निंग मॉडल, जिन्हें जरूरत पड़ने पर दोबारा डाउनलोड किया जा सकता है
इन्हें छोड़ना एक समझौता है, कोई मुफ्त लाभ नहीं। एक बड़ी लाइब्रेरी के लिए थंबनेल और ट्रांसकोड को दोबारा बनाना एक छोटे VPS पर CPU के कई घंटों का काम है, और इस दौरान टाइमलाइन पर केवल ग्रे प्लेसहोल्डर दिखाई देंगे। आप इन्हें Administration > Jobs में जाकर, "Generate Thumbnails" और "Transcode Videos" को missing assets पर सेट करके दोबारा चला सकते हैं। यदि आपके बैकअप टारगेट में जगह है, तो इन्हें शामिल करें और प्रतीक्षा से बचें। यदि आप अपनी स्टोरेज सीमा के करीब हैं, तो इन्हें हटा दें और दोबारा बनाने की योजना रखें। Immich लाइब्रेरी का आकार तय करना में बताया गया है कि ये फोल्डर ओरिजिनल फाइलों की तुलना में कितने बड़े हो जाते हैं।
एक और फोल्डर के बारे में जानना उपयोगी है। UPLOAD_LOCATION/backups में Immich के अपने स्वचालित डेटाबेस डंप होते हैं, जो प्रतिदिन 02:00 बजे लिखे जाते हैं और पिछले 14 डंप सुरक्षित रखे जाते हैं, जिन्हें Administration > Settings > Backup के तहत कॉन्फ़िगर किया जा सकता है। इनकी कोई अतिरिक्त लागत नहीं है और ये वास्तव में उपयोगी हैं। ये उसी डिस्क पर होते हैं जिस लाइब्रेरी की ये सुरक्षा करते हैं, इसलिए ये खराब माइग्रेशन में तो मदद करते हैं, लेकिन सर्वर डेड होने पर नहीं। फिर भी अपना डंप स्वयं लें, क्योंकि आपके द्वारा ट्रिगर किया गया डंप उसी समय पर होता है जिस समय फाइल स्नैपशॉट लिया जाता है।
डेटाबेस डंप लें
docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres \
| gzip > /srv/immich/backup/immich.sql.gzयदि आपने immich और postgres को बदल दिया है, तो उन्हें अपने DB_DATABASE_NAME और DB_USERNAME से बदलें। --clean --if-exists हर CREATE के आगे एक DROP ... IF EXISTS लगा देता है, ताकि डंप उन ऑब्जेक्ट्स वाले डेटाबेस में भी रिप्ले हो सके जिनमें पहले से डेटा मौजूद है, बजाय इसके कि वह पहले ऑब्जेक्ट पर ही रुक जाए।
अब वह विवरण जो चुपचाप बैकअप स्क्रिप्ट्स को बर्बाद कर देता है। वह कमांड एक पाइपलाइन है, और शेल पाइपलाइन में अंतिम कमांड का एक्जिट स्टेटस रिपोर्ट करता है। यदि pg_dump विफल हो जाता है, जैसे गलत पासवर्ड या कंटेनर के न चलने के कारण, तो gzip को एक खाली स्ट्रीम प्राप्त होती है, वह एक पूरी तरह से वैध gzip फाइल लिखता है, और 0 के साथ एक्जिट हो जाता है। आपकी स्क्रिप्ट सफलता लॉग करती है और आपके पास 20-बाइट का बैकअप रह जाता है। हर बैकअप स्क्रिप्ट के शीर्ष पर pipefail रखें:
#!/usr/bin/env bash
set -euo pipefailफिर एक्जिट कोड पर भरोसा करने के बजाय परिणाम की जाँच करें:
ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3एक सही डंप की पहली पंक्ति -- PostgreSQL database dump पढ़ती है। कुछ सौ बाइट्स की फाइल एक विफल डंप है, चाहे स्क्रिप्ट ने कुछ भी कहा हो।
डंप के साथ यह रिकॉर्ड करें कि किस बिल्ड ने इसे लिखा है:
docker inspect --format '{{.Config.Image}}' immich_server > /srv/immich/backup/immich-version.txtइसके लिए .env पर निर्भर न रहें। स्टॉक फाइल IMMICH_VERSION=v3 सेट करती है, जो एक फ्लोटिंग टैग है और हर 3.x रिलीज के साथ बदलता है, इसलिए यह आपको यह नहीं बताता कि वास्तव में किस बिल्ड ने डंप लिखा है। .env में भी सटीक टैग को पिन करें।
सर्वर को रोकें, फिर restic के साथ स्नैपशॉट लें
जब Immich चल रहा होता है, तो UPLOAD_LOCATION के अंतर्गत मौजूद फाइलें immutable नहीं होती हैं। सर्वर नए अपलोड लिखता है और स्टोरेज टेम्प्लेट जॉब फाइलों को डायरेक्टरी के बीच स्थानांतरित करती है। यदि कोई बैकअप टूल लिखते समय किसी फाइल को बीच में ही पढ़ लेता है, तो वह उन बाइट्स को पूरी फाइल मानकर स्टोर कर लेता है, और किसी को भी त्रुटि (error) का पता नहीं चलता। बैकअप चलने के दौरान सर्वर कंटेनर को रोक दें:
docker stop immich_serverimmich_postgres को चलते रहने दें, क्योंकि डंप के लिए इसकी आवश्यकता होती है। जब तक आप सर्वर को फिर से शुरू नहीं करते, तब तक वेब इंटरफेस और मोबाइल ऐप ऑफलाइन रहेंगे, जो कि घरेलू उपयोग वाले इंस्टेंस पर 03:00 बजे के समय आमतौर पर ठीक रहता है।
restic यहाँ उपयुक्त है क्योंकि यह डेटा के बाहर जाने से पहले उसे deduplicate और encrypt करता है। इसे ऐसे रिपॉजिटरी पर पॉइंट करें जो इस सर्वर पर न हो:
export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic initऑब्जेक्ट स्टोरेज भी इसी तरह काम करता है, और यदि आप कॉपी को पूरी तरह से अपने हार्डवेयर से बाहर रखना चाहते हैं तो यह एक बेहतर विकल्प है:
export RESTIC_REPOSITORY=s3:https://s3.example.com/immich-backup
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
restic initवह एंडपॉइंट एक MinIO बकेट हो सकता है जिसे आप स्वयं चलाते हैं किसी दूसरी मशीन पर, या कोई भी S3-compatible प्रदाता। लाइब्रेरी वाली डिस्क पर ही रिपॉजिटरी रखने से आप केवल गलती से डिलीट होने से बच सकते हैं, किसी और चीज से नहीं।
फिर स्नैपशॉट लें, जिसमें केवल वही शामिल करें जो महत्वपूर्ण है:
restic backup \
/srv/immich/backup/immich.sql.gz \
/srv/immich/backup/immich-version.txt \
/srv/immich/data/library \
/srv/immich/data/upload \
/srv/immich/data/profile \
/srv/immich/.env \
/srv/immich/docker-compose.yml
docker start immich_serverrestic हर बार पूरी ट्री को पढ़ता है लेकिन केवल उन्हीं ब्लॉक्स को अपलोड करता है जिन्हें उसने पहले नहीं देखा है, इसलिए पहला स्नैपशॉट आपकी पूरी लाइब्रेरी को स्थानांतरित करता है और उसके बाद के हर स्नैपशॉट में केवल उस दिन की नई तस्वीरें ही स्थानांतरित होती हैं।
रिटेंशन, और वे कुंजियाँ जो कहीं और होनी चाहिए
restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12forget इंडेक्स से स्नैपशॉट्स को हटा देता है। --prune वह हिस्सा है जो उन डेटा को डिलीट करता है जिनके लिए वे स्नैपशॉट्स अंतिम संदर्भ थे। forget को --prune के बिना चलाएं तो आपका स्टोरेज बिल कभी कम नहीं होगा।
स्ट्रक्चर चेक सस्ते होते हैं, इसलिए इन्हें साप्ताहिक रूप से चलाएं:
restic checkयह सत्यापित करता है कि रिपॉजिटरी मेटाडेटा सुसंगत है। यह आपके डेटा को नहीं पढ़ता है। महीने में एक बार, एक नमूने को दोबारा पढ़ें और इसे उसके रिकॉर्ड किए गए हैश के साथ जांचें:
restic check --read-data-subset=5%यह एकमात्र चेक है जो स्टोरेज बैकएंड पर साइलेंट करप्शन (silent corruption) को पकड़ता है, क्योंकि यह वास्तविक ब्लॉक्स को डाउनलोड करता है और उनके चेकसम की पुनर्गणना करता है। फोटो लाइब्रेरी पर पूर्ण --read-data का अर्थ है पूरी रिपॉजिटरी को डाउनलोड करना, जो मीटर वाले ऑब्जेक्ट स्टोरेज पर वास्तविक पैसे खर्च करवाता है, इसलिए लोग वास्तव में एक रोलिंग सबसेट (rolling subset) ही चलाते हैं।
अब वह हिस्सा जिसे लोग छोड़ देते हैं। restic रिपॉजिटरी पासवर्ड रिकवर नहीं किया जा सकता है। इसका कोई रीसेट नहीं है और न ही कोई सपोर्ट टिकट। यदि इसकी एकमात्र कॉपी उसी सर्वर पर /root/.restic-password में मौजूद है जिसे आप रिस्टोर करने की कोशिश कर रहे हैं, तो आपके बैकअप केवल एन्क्रिप्टेड शोर (encrypted noise) हैं। यही बात ऑब्जेक्ट स्टोरेज एक्सेस की और .env से DB_PASSWORD के लिए भी लागू होती है। इन सभी को ऐसी जगह रखें जो इस मशीन के चालू रहने पर निर्भर न हो: प्रिंट करके दराज में रखें, या किसी अलग हार्डवेयर पर चल रहे पासवर्ड मैनेजर में रखें। यदि वह मैनेजर भी self-hosted है, तो उसे भी समान सुरक्षा की आवश्यकता है, और Vaultwarden का बैकअप लेना अपने आप में एक अलग कार्य है।
Immich को सही क्रम में रिस्टोर करें
रिस्टोर का क्रम ही वह बिंदु है जहाँ अच्छे बैकअप भी खाली टाइमलाइन में बदल सकते हैं। नए होस्ट पर इस क्रम का पालन करें।
सबसे पहले कॉन्फ़िगरेशन वापस लाएं। यह आपको बताता है कि कौन सा वर्ज़न चलाना है और पाथ कहाँ पॉइंट करते हैं।
restic restore latest --target /restore \
--include /srv/immich/.env \
--include /srv/immich/docker-compose.yml \
--include /srv/immich/backupशुरू करने से पहले वर्ज़न को पिन करें। immich-version.txt पढ़ें, .env में IMMICH_VERSION को उस सटीक टैग पर सेट करें, और अभी के लिए सबसे नए रिलीज़ को न छुएं। Immich डाउनग्रेडिंग को सपोर्ट नहीं करता है, यहाँ तक कि पैच रिलीज़ के बीच भी नहीं। यदि कोई नया सर्वर पुराने डंप के विरुद्ध शुरू होता है और माइग्रेशन चला देता है, तो वापस जाने का कोई रास्ता नहीं है।
मीडिया को रिस्टोर करें।
restic restore latest --target /restore --include /srv/immich/dataफिर library, upload और profile को मूव करें ताकि वे सीधे उस स्थान पर हों जहाँ इस होस्ट पर UPLOAD_LOCATION पॉइंट करता है। होस्ट पाथ बदल सकता है, क्योंकि compose फ़ाइल उस डायरेक्टरी को कंटेनर के अंदर एक निश्चित पाथ पर बाइंड करती है। इसके अंदर का लेआउट नहीं बदल सकता।
डेटाबेस को अकेले स्टार्ट करें। DB_DATA_LOCATION को खाली छोड़ दें ताकि Postgres एक नया क्लस्टर इनिशियलाइज़ कर सके।
cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgrespg_isready पहली बार सेटअप पूरा होने पर accepting connections प्रिंट करता है, जिसमें कुछ सेकंड लगते हैं। docker compose create हर कंटेनर को बिना स्टार्ट किए बिल्ड करता है, और इस स्टेप का यही मुख्य उद्देश्य है: Immich सर्वर अभी चलना नहीं चाहिए। एक सर्वर जो खाली डेटाबेस के विरुद्ध शुरू होता है, वह अपने माइग्रेशन लागू करता है, एक नया स्कीमा बनाता है और आपसे नया एडमिन अकाउंट बनाने के लिए कहता है। ऐसी स्थिति में आप एक चलते हुए एप्लिकेशन के नीचे डंप को रिप्ले कर रहे होते हैं।
डंप को रिप्ले करें।
gunzip --stdout /restore/srv/immich/backup/immich.sql.gz \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| docker exec -i immich_postgres psql --dbname=immich --username=postgres \
--single-transaction --set ON_ERROR_STOP=onइसमें दो हिस्से वास्तविक काम कर रहे हैं। sed इसलिए मौजूद है क्योंकि pg_dump सुरक्षा उपाय के रूप में अपने आउटपुट में एक खाली search_path लिखता है, ताकि डंप में अनक्वालिफाइड नाम किसी अनपेक्षित स्कीमा पर रिज़ॉल्व न हों। Immich के वेक्टर-सर्च टाइप public में रहते हैं, इसलिए खाली सर्च पाथ के साथ रिस्टोर उस पहले कॉलम तक पहुँचता है जिसे वेक्टर टाइप के साथ घोषित किया गया है और psql ERROR: type "vector" does not exist के साथ रुक जाता है। public को वापस पाथ पर रखने से यह ठीक हो जाता है।
--single-transaction --set ON_ERROR_STOP=on पूरे रिस्टोर को एक ट्रांजेक्शन में लपेटता है जो पहली त्रुटि पर एबॉर्ट हो जाता है। आपको या तो एक पूर्ण डेटाबेस मिलता है या एक अनछुआ डेटाबेस। इसके बिना, बीच में विफलता होने पर एक ऐसा डेटाबेस रह जाता है जो स्टार्ट तो हो जाता है और आपका लॉगिन स्वीकार कर लेता है, लेकिन उसमें अज्ञात संख्या में एल्बम गायब होते हैं, जिसका पता आपको हफ़्तों बाद चलता है।
अब सब कुछ स्टार्ट करें।
docker compose up -d
docker compose ps
docker logs -f immich_serverImmich Server is listening on जैसी स्टार्टअप लाइन की प्रतीक्षा करें, फिर पोर्ट 2283 खोलें और अपने पुराने क्रेडेंशियल्स के साथ लॉगिन करें, क्योंकि यूजर अकाउंट डंप के साथ वापस आ गए हैं। यदि लॉगिन पेज इसके बजाय पहला एडमिन अकाउंट बनाने का विकल्प देता है, तो डेटाबेस रिस्टोर नहीं हुआ है। रुकें और psql आउटपुट को फिर से पढ़ें।
आधिकारिक रिस्टोर निर्देशों के बारे में एक चेतावनी, जो docker compose down -v के साथ शुरू होते हैं। -v नेम्ड वॉल्यूम को हटा देता है। स्टॉक compose फ़ाइल में UPLOAD_LOCATION और DB_DATA_LOCATION बाइंड माउंट हैं, इसलिए वे इससे सुरक्षित रहते हैं। यदि आपने किसी एक को नेम्ड वॉल्यूम में बदल दिया है, तो वह कमांड आपकी तस्वीरें डिलीट कर देगी। कमांड टाइप करने से पहले अपनी compose फ़ाइल ज़रूर पढ़ें।
Restore के बाद timeline खाली क्यों दिखती है
Timeline डेटाबेस की पंक्तियों (rows) से तैयार होती है। Immich बूट होने पर फोटो को फिर से खोजने के लिए कभी भी upload/ को स्कैन नहीं करता है, क्योंकि जिस फाइल की कोई पंक्ति नहीं है, उसका न तो कोई मालिक होता है, न तारीख और न ही कोई एल्बम। इसलिए, सबसे आम गलत restore वह है जिसमें फाइलें तो वापस आ जाती हैं, लेकिन डेटाबेस गायब होता है। Immich शुरू होता है, एक खाली schema बनाता है, और आपको एक काम करने वाला instance देता है जिसमें कुछ भी नहीं है, जबकि डिस्क आपकी फोटो से भरी होती है। कुछ भी खोया नहीं है। बस कुछ भी दिखाई नहीं दे रहा है। इसे ठीक करने का तरीका यह है कि सर्वर को बंद करके dump को फिर से replay करें, ठीक वैसे ही जैसे ऊपर बताया गया है।
दूसरा संस्करण अधिक शांत है। डेटाबेस restore हो जाता है, timeline प्रविष्टियों से भर जाती है, लेकिन कोई भी asset खुल नहीं पाता है। इसका मतलब है कि पंक्तियाँ उन फाइलों की ओर इशारा कर रही हैं जिन्हें container देख नहीं सकता है। ऐसा आमतौर पर तब होता है जब library, upload और profile एक restic restore --target /restore के बाद एक स्तर बहुत गहरे (too deep) होते हैं जिसे किसी ने सही जगह पर नहीं रखा है। अनुमान लगाने के बजाय container के अंदर से जाँच करें:
docker exec immich_server ls /dataStandard compose फाइल UPLOAD_LOCATION को /data पर mount करती है, इसलिए उस listing में library, upload और profile दिखाई देने चाहिए। यदि यह एक खाली directory या कोई अतिरिक्त srv फोल्डर दिखाता है, तो आपका bind mount गलत स्तर पर पॉइंट कर रहा है और पंक्तियाँ बिल्कुल सही हैं।
Backup और restore के बीच version का मिलान
Immich के releases अक्सर आते हैं और इसके साथ schema भी बदलता रहता है, इसलिए dump में उसी server का schema होता है जिसने उसे लिखा था।
पुराने dump को नए server पर restore करना आमतौर पर काम करता है, क्योंकि server start होने पर अपने pending migrations को लागू करता है और schema को आगे बढ़ाता है। यह path release sequence के दौरान test किया जाता है। एक ही बार में कई major versions को jump करने पर समस्या होती है, और project breaking changes को major releases तक सीमित रखता है और उन्हें अपने changelog में document करता है।
नए dump को पुराने server पर restore करना बिल्कुल काम नहीं करता है। dump में ऐसी tables और columns होते हैं जिनके बारे में पुराने code को जानकारी नहीं होती, और Immich यह स्पष्ट करता है कि patch releases के बीच भी downgrade करना समर्थित (unsupported) नहीं है। यहाँ उपयोग करने के लिए कोई rollback command नहीं है।
इसलिए, सुरक्षित restore का तरीका सरल और व्यवस्थित है। उसी exact version को चलाएं जिसने dump लिखा था, उसे replay करें, login करें, पुष्टि करें कि timeline पूर्ण है, और उसके बाद ही upgrade करें। एक बार में एक release को upgrade करें, हर bump के बाद IMMICH_VERSION को बढ़ाएं और docker compose pull && docker compose up -d को चलाएं। एक सप्ताह के dumps को सुरक्षित रखना यहाँ भी मदद करता है: यदि सबसे नया dump किसी failed upgrade के दौरान लिया गया हो, तो कल का dump repository में उपलब्ध रहता है।
हर महीने बैकअप को सत्यापित करें
जिस बैकअप को आपने कभी रिस्टोर नहीं किया है, वह केवल एक अनुमान है। महीने में एक बार, इसे एक अस्थायी इंस्टेंस (throwaway instance) में रिस्टोर करें और एक फोटो देखें। इस अभ्यास में लगभग बीस मिनट लगते हैं और यही एकमात्र तरीका है जिससे इस पृष्ठ पर दी गई बाकी जानकारी एक रिकवरी प्लान में बदलती है।
restic snapshots
restic stats latestsnapshots में पिछली रात का रन दिखना चाहिए। stats latest को आपकी लाइब्रेरी के आकार के करीब का डेटा दिखाना चाहिए, न कि केवल कुछ मेगाबाइट्स।
एक स्क्रैच डायरेक्टरी में रिस्टोर करें, आदर्श रूप से किसी अतिरिक्त होस्ट पर:
restic restore latest --target /tmp/immich-drillरिस्टोर किए गए सेट से docker-compose.yml और .env को कॉपी करें, फिर कॉपी में तीन चीजें बदलें। UPLOAD_LOCATION और DB_DATA_LOCATION को /tmp/immich-drill के अंतर्गत डायरेक्टरीज़ पर पॉइंट करें। वेब पोर्ट को कहीं और पब्लिश करें, 2283:2283 के बजाय 12283:2283 का उपयोग करें। container_name: लाइनों को हटा दें, क्योंकि स्टॉक compose फाइल में immich_server जैसे नाम हार्ड-कोड होते हैं, इसलिए उसी होस्ट पर दूसरा स्टैक पहले वाले के साथ टकराएगा और Docker इसे बनाने से मना कर देगा।
ऊपर दी गई रिस्टोर प्रक्रिया चलाएँ: केवल डेटाबेस, डंप को रिप्ले करें, फिर docker compose up -d चलाएँ। अब वे चार जाँचें करें जो यह साबित करती हैं कि सब कुछ सही है।
- उस पासवर्ड से लॉग इन करें जिसका उपयोग आपने अभ्यास से पहले किया था। काम करने वाले अकाउंट्स का मतलब है कि डंप सफलतापूर्वक रिस्टोर हो गया है।
- टाइमलाइन खोलें और सबसे पुराने महीने तक स्क्रॉल करें। पूरी डेट रेंज में एसेट्स दिखने का मतलब है कि सभी पंक्तियाँ वापस आ गई हैं, न कि केवल हाल की।
- एक फोटो को फुल साइज में खोलें और ओरिजिनल फाइल डाउनलोड करें।
sha256sumका उपयोग करके इसकी तुलना अपनी लाइव लाइब्रेरी की उसी फाइल से करें। मैचिंग हैश का मतलब है कि बाइट्स restic के माध्यम से राउंड ट्रिप में सुरक्षित रहे।
फिर अभ्यास डायरेक्टरी में docker compose down -v के साथ सेटअप को हटा दें और /tmp/immich-drill को डिलीट कर दें। तारीख को कहीं ऐसी जगह लिखें जहाँ आप उसे देख सकें, क्योंकि इसका महत्व पूरी तरह से इसे अगले महीने फिर से करने में है। यदि आप अभी भी यह तय कर रहे हैं कि किस फोटो सर्वर का उपयोग करना है, तो PhotoPrism और Immich की तुलना में बताया गया है कि ये दोनों इस आधार पर कैसे भिन्न हैं।
FAQ
क्या मुझे बैकअप लेने के लिए Immich को रोकना होगा?
immich_server को रोकें और immich_postgres को चलता रहने दें। डेटाबेस को रोकने की आवश्यकता नहीं है, क्योंकि pg_dump एक MVCC स्नैपशॉट के भीतर पढ़ता है और उसे एक ही सुसंगत क्षण दिखाई देता है, चाहे कुछ भी लिखा जा रहा हो। फाइलें ही रोकने का कारण हैं: सर्वर नए अपलोड लिखता है और स्टोरेज टेम्पलेट जॉब फाइलों को डायरेक्टरी के बीच ले जाता है, इसलिए बैकअप टूल किसी फाइल को लिखते समय बीच में ही पढ़ सकता है और बिना किसी त्रुटि के एक अधूरी कॉपी स्टोर कर सकता है। स्नैपशॉट से पहले docker stop immich_server और उसके बाद docker start immich_server इस रेस कंडीशन को हटा देते हैं।
क्या मैं pg_dump चलाने के बजाय Postgres डेटा फोल्डर को कॉपी कर सकता हूँ?
नहीं। लाइव डेटा डायरेक्टरी की रोलिंग कॉपी अलग-अलग समय पर अलग-अलग फाइलें पढ़ती है, इसलिए परिणाम एक सुसंगत स्थिति नहीं होती है, और Postgres स्टार्टअप पर PANIC: could not locate a valid checkpoint record के साथ इसे अस्वीकार कर देता है या बाद में क्षतिग्रस्त पेज पर विफल हो जाता है। यहाँ तक कि सब कुछ रोककर ली गई कॉपी भी सटीक डेटाबेस बिल्ड से जुड़ी होती है: Immich एक Postgres 14 इमेज को विशिष्ट वेक्टर-सर्च एक्सटेंशन संस्करणों के साथ पिन करता है, और वह डायरेक्टरी किसी अन्य चीज़ के तहत नहीं खुलेगी। SQL डंप सादा टेक्स्ट होता है और किसी भी संगत सर्वर में फिर से चलाया जा सकता है।
रिस्टोर के बाद मेरी Immich टाइमलाइन खाली क्यों है?
क्योंकि टाइमलाइन डेटाबेस पंक्तियों (rows) से बनी होती है और आपने डेटाबेस के बिना फाइलें रिस्टोर की हैं। Immich फोटो को फिर से खोजने के लिए कभी भी upload/ को स्कैन नहीं करता है, इसलिए बिना पंक्तियों वाली फाइलें अदृश्य रहती हैं। फोटो स्वयं सुरक्षित हैं। सर्वर को रोकें, डंप को एक नए इनिशियलाइज़ किए गए Postgres में रिप्ले करें, फिर स्टैक को स्टार्ट करें। यदि इसके विपरीत टाइमलाइन भरी हुई है लेकिन कोई भी फोटो नहीं खुल रही है, तो समस्या उल्टी है: library, upload और profile सीधे उस डायरेक्टरी के अंदर नहीं हैं जो कंटेनर में बाउंड है। इसे docker exec immich_server ls /data के साथ जांचें।
मैं बैकअप में कौन से Immich फोल्डर छोड़ सकता हूँ?
thumbs और encoded-video मूल फाइलों से फिर से बन जाते हैं, और DB_DATA_LOCATION डंप से फिर से बन जाता है, इसलिए इनमें से किसी को भी बैकअप सेट में होने की आवश्यकता नहीं है। इन्हें छोड़ने से स्टोरेज के बजाय रिस्टोर के बाद समय लगता है, क्योंकि एक बड़ी लाइब्रेरी के लिए प्रीव्यू और ट्रांसकोड को फिर से बनाना घंटों का CPU कार्य है, जिसे Administration > Jobs से गायब एसेट्स के खिलाफ चलाया जाता है। जिसे आप कभी नहीं छोड़ सकते वह library, upload और profile हैं, जिनमें हर ओरिजिनल फाइल की एकमात्र कॉपी होती है।
क्या मैं Immich डंप को नए संस्करण में रिस्टोर कर सकता हूँ?
आमतौर पर हाँ, क्योंकि सर्वर स्टार्ट होने पर अपने लंबित माइग्रेशन को लागू करता है और स्कीमा को आगे बढ़ाता है। उल्टा विफल हो जाता है: Immich डाउनग्रेडिंग का समर्थन नहीं करता है, यहाँ तक कि पैच रिलीज़ के बीच भी नहीं, इसलिए नए रिलीज़ से लिए गए डंप को पुराने सर्वर में लोड नहीं किया जा सकता है। उस रिलीज़ के साथ IMMICH_VERSION पिन करके रिस्टोर करें जिसने डंप लिखा था, पुष्टि करें कि टाइमलाइन पूर्ण है, और उसके बाद अपग्रेड करें। प्रत्येक डंप के साथ docker inspect --format '{{.Config.Image}}' immich_server का उपयोग करके संस्करण रिकॉर्ड करें, क्योंकि डिफ़ॉल्ट IMMICH_VERSION=v3 एक फ्लोटिंग टैग है जो आपको कुछ नहीं बताता है।