Immich का बैकअप और रिस्टोर कैसे करें: पूरी गाइड
Immich का सही बैकअप लेने के लिए Postgres SQL डंप और UPLOAD_LOCATION का होना जरूरी है। Postgres डेटा डायरेक्टरी की लाइव कॉपी न लें। गलत रिस्टोर से टाइमलाइन खाली दिख सकती है।
Immich बैकअप में क्या होना चाहिए
Immich बैकअप का मतलब है एक ही समय पर ली गई तीन चीजें। UPLOAD_LOCATION के अंतर्गत मौजूद originals। Postgres डेटाबेस का एक SQL dump। और वे .env व docker-compose.yml जो stack का विवरण देते हैं। Restore करने का अर्थ है कि Immich सर्वर को रोककर उस dump को एक नए डेटाबेस में फिर से लोड करना, और उसके बाद ही बाकी stack को शुरू करना। यदि क्रम गलत हुआ, तो आपके पास एक चालू Immich तो होगा, लेकिन पूरी डिस्क होने के बावजूद timeline खाली दिखाई देगी।
यह विभाजन महत्वपूर्ण है क्योंकि Immich अपनी स्थिति (state) को दो ऐसी जगहों पर रखता है जो एक-दूसरे के बारे में कुछ नहीं जानतीं। Postgres में हर album, हर face cluster, हर shared link, हर user account, API key और प्रत्येक asset का stored path होता है। Filesystem में pixels होते हैं। डेटाबेस के बिना फाइलों को restore करने पर Immich कुछ नहीं दिखाएगा। फाइलों के बिना डेटाबेस को restore करने पर हर asset एक टूटी हुई image के रूप में खुलेगा।
यहाँ दिए गए commands Immich v3.1.0 के लिए लिखे गए हैं, जो अगस्त 2026 की शुरुआत में current release था। 2026-10-25 तक current release v3.3.5 है, जो 2026-10-21 को जारी किया गया एक security patch है, और इसकी compose file, database image तथा documented backup और restore प्रक्रियाएँ इस पेज के अनुरूप हैं। यह प्रोजेक्ट बहुत तेजी से आगे बढ़ता है और documented backup प्रक्रिया एक से अधिक बार बदल चुकी है, इसलिए कुछ भी copy करने से पहले यह जाँच लें कि आप वास्तव में कौन सा version चला रहे हैं। यदि stack अभी तक तैयार नहीं है, तो Immich install guide से शुरुआत करें और फिर वापस आएँ।
जानें कि आपके 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 डेटा डायरेक्टरी को copy करना बैकअप क्यों नहीं है
DB_DATA_LOCATION एक आसान लक्ष्य की तरह दिखता है। यह एक डायरेक्टरी है, rsync इसे copy कर देगा, और copy बिना किसी error के पूरी हो जाएगी। यदि आप Postgres के चलते समय इसे copy करते हैं, तो वह copy बैकअप नहीं है। यदि आप Postgres को रोककर इसे copy करते हैं, तो यह एक बैकअप तो है, लेकिन बहुत नाजुक। इसके दो कारण हैं, और आप दोनों को विफल होते देख सकते हैं।
पहला कारण है tearing। Postgres हर बदलाव को पहले write-ahead log (WAL) में लिखता है, और बाद में checkpoint पर उसे table फाइलों में लागू करता है। इसलिए किसी भी क्षण डिस्क पर मौजूद फाइलें बीच की स्थिति में होती हैं, और चार मिनट तक चलने वाली एक rolling copy 02:00 बजे पहली फाइल पढ़ती है और 02:04 बजे आखिरी। वे दोनों फाइलें एक ही transaction का हिस्सा नहीं होतीं। जब आप परिणाम पर Postgres शुरू करते हैं, तो या तो वह startup पर PANIC: could not locate a valid checkpoint record के साथ मना कर देता है, या फिर शुरू होने के बाद किसी क्षतिग्रस्त page को पढ़ते समय invalid page in block 1234 of relation base/16384/... के साथ बंद हो जाता है। उस copy से कुछ भी recover नहीं किया जा सकता।
दूसरा कारण उस copy के बारे में है जो आप सब कुछ रोककर लेते हैं। PostgreSQL एक बंद डेटा डायरेक्टरी की पूरी copy को एक वैध बैकअप के रूप में स्वीकार करता है, लेकिन वह डायरेक्टरी केवल उन्हीं binaries के साथ खुलती है जो उसके storage format को साझा करती हैं। Immich अपनी database image को digest द्वारा pin करता है, जो वर्तमान में ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 है। यह Postgres 14 है जिसमें VectorChord, pgvector और pgvecto.rs vector-search extensions पहले से शामिल हैं। Immich अब VectorChord पर चलता है; pgvecto.rs उस image में केवल इसलिए रहता है ताकि पुराने installs उससे migrate हो सकें और पुराने backups को अभी भी restore किया जा सके। Postgres 14 का बाद का कोई minor release उस डायरेक्टरी को बिना बदले खोल सकता है, लेकिन कोई अलग Postgres major version ऐसा नहीं कर सकता। जिन extensions पर आपकी tables निर्भर करती हैं, उनका भी मौजूद होना और compatible version में होना आवश्यक है। आपके restore host पर एक compatible image चलनी चाहिए। SQL dump को इससे कोई फर्क नहीं पड़ता: यह text है, और कोई भी compatible सर्वर इसे replay कर सकता है।
pg_dump tearing की समस्या को पूरी तरह से टाल देता है। यह एक ही MVCC (multi-version concurrency control) snapshot के भीतर पूरे डेटाबेस को पढ़ता है, इसलिए यह डेटाबेस को बिल्कुल उसी स्थिति में देखता है जैसी वह एक क्षण में थी, जबकि उसके आसपास अन्य writes जारी रहते हैं। यही कारण है कि dump लेने के लिए आपको Postgres को रोकने की आवश्यकता नहीं है।
बैकअप से आप क्या छोड़ सकते हैं
ये फाइलें दोबारा बन जाती हैं, इसलिए आप इन्हें छोड़ सकते हैं:
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 > Database Dump Settings के तहत कॉन्फ़िगर किया जा सकता है। इनकी कोई अतिरिक्त लागत नहीं है और ये वास्तव में उपयोगी हैं। ये उसी डिस्क पर होते हैं जिस लाइब्रेरी की ये सुरक्षा करते हैं, इसलिए ये खराब माइग्रेशन में तो मदद करते हैं, लेकिन सर्वर खराब होने पर नहीं। अपना डंप खुद भी लें, क्योंकि आपके द्वारा ट्रिगर किया गया डंप उसी क्षण प्राप्त होता है जिस क्षण उसके साथ वाली फाइल का स्नैपशॉट लिया जाता है।
डेटाबेस डंप लें
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 लगा देता है, ताकि डंप किसी ऐसे डेटाबेस में रिप्ले (replay) हो सके जिसमें पहले से ऑब्जेक्ट्स मौजूद हैं, बजाय इसके कि वह पहले ऑब्जेक्ट पर ही रुक जाए।
अब वह विवरण जो चुपचाप बैकअप स्क्रिप्ट्स को बर्बाद कर देता है। वह कमांड एक पाइपलाइन है, और शेल पाइपलाइन में अंतिम कमांड का एक्जिट स्टेटस रिपोर्ट करता है। यदि 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 पढ़ती है। कुछ सौ बाइट्स की फाइल एक विफल डंप है, चाहे स्क्रिप्ट ने कुछ भी कहा हो।
चल रहे सर्वर से पूछकर रिकॉर्ड करें कि किस रिलीज ने इसे लिखा है, डंप के बगल में:
curl -fsS http://localhost:2283/api/server/version > /srv/immich/backup/immich-version.txtउस एंडपॉइंट को किसी लॉगिन की आवश्यकता नहीं है और वह चल रही रिलीज को मेजर, माइनर और पैच नंबर के रूप में लौटाता है, इसलिए 3, 1 और 0 का मतलब v3.1.0 है। इसके लिए .env पर भरोसा न करें, या docker inspect --format '{{.Config.Image}}' immich_server पर, जो केवल आपके द्वारा कॉन्फ़िगर किए गए इमेज रेफरेंस को इको (echo) करता है। स्टॉक फाइल IMMICH_VERSION=v3 सेट करती है, एक फ्लोटिंग टैग जो हर 3.x रिलीज का अनुसरण करता है, इसलिए :v3 पर समाप्त होने वाला रिकॉर्ड आपको यह नहीं बताता कि वास्तव में किस बिल्ड ने डंप लिखा है। .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 को उस सटीक रिलीज़ पर सेट करें (v3.1.0 मेजर 3, माइनर 1, पैच 0 के लिए), और अभी के लिए सबसे नए रिलीज़ को न छुएं। 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 गलत स्तर पर पॉइंट कर रहा है और पंक्तियाँ बिल्कुल सही हैं।
बैकअप और restore के बीच version का मिलान
Immich के releases अक्सर आते हैं और schema उसके साथ बदलता रहता है, इसलिए dump में उसी सर्वर का schema होता है जिसने उसे लिखा था।
एक पुराने dump को नए सर्वर में restore करना आमतौर पर काम करता है, क्योंकि सर्वर शुरू होने पर अपने pending migrations को लागू करता है और schema को आगे बढ़ाता है। Immich के अपने backup docs अभी भी सलाह देते हैं कि जहाँ संभव हो, एक compatible version में ही restore करें, क्योंकि version mismatch का मतलब है कि restore के दौरान migrations चलेंगे। प्रोजेक्ट major releases में breaking changes करता रहता है और उन्हें अपने release notes में document करता है, इसलिए यदि restore किसी major version को पार कर रहा है, तो पहले उसके बारे में पढ़ लें।
एक नए dump को पुराने सर्वर में restore करना बिल्कुल काम नहीं करता। dump में ऐसी tables और columns होती हैं जिनके बारे में पुराने code को जानकारी नहीं होती, और Immich का कहना है कि patch releases के बीच भी downgrading समर्थित नहीं है। यहाँ कोई rollback command उपलब्ध नहीं है।
इसलिए सुरक्षित restore का तरीका उबाऊ है। वही exact version चलाएँ जिसने dump लिखा था, उसे replay करें, login करें, पुष्टि करें कि timeline पूरी है, और उसके बाद ही upgrade करें। उसी तरह upgrade करें जैसा official upgrade पेज बताता है: breaking changes के लिए release notes पढ़ें, .env में IMMICH_VERSION को उस release पर सेट करें जिसे आप चाहते हैं, और फिर 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 के चलते समय ऐसा नहीं किया जा सकता। एक लाइव डेटा डायरेक्टरी की रोलिंग कॉपी अलग-अलग समय पर अलग-अलग फाइलें पढ़ती है, इसलिए परिणाम एक सुसंगत स्थिति में नहीं होता, और Postgres स्टार्टअप पर PANIC: could not locate a valid checkpoint record के साथ इसे अस्वीकार कर देता है या बाद में क्षतिग्रस्त पेज के कारण विफल हो जाता है। Postgres को रोककर ली गई पूरी कॉपी एक वैध बैकअप है, लेकिन यह केवल उसी Postgres मेजर वर्जन और संगत एक्सटेंशन के साथ खुलती है। Immich, VectorChord, pgvector और pgvecto.rs के साथ 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 का उपयोग करके रिस्टोर करें जिसने डंप बनाया था, पुष्टि करें कि टाइमलाइन पूरी है, और उसके बाद अपग्रेड करें। प्रत्येक डंप के साथ curl -fsS http://localhost:2283/api/server/version का उपयोग करके रिलीज का रिकॉर्ड रखें, क्योंकि docker inspect केवल कॉन्फ़िगर की गई इमेज रेफरेंस दिखाता है, और डिफ़ॉल्ट IMMICH_VERSION=v3 एक फ्लोटिंग टैग है जो कोई जानकारी नहीं देता।