SSD Nodes Learn 🎉 VPS $5.50/माह से
गाइड Matt Connorलेखक: Matt Connor

Server को नए VPS पर कैसे माइग्रेट करें: पूरी गाइड

एक live server को नए VPS पर सुरक्षित रूप से माइग्रेट करने का तरीका जानें। इसमें DNS TTL कम करने, database dump और rehearsed cutover की सटीक प्रक्रिया शामिल है ताकि downtime न हो।

एक नए VPS पर सर्वर को rehearsed cutover के रूप में माइग्रेट करना

सर्वर को नए VPS पर माइग्रेट करने के लिए, इसे केवल कॉपी करने के बजाय एक rehearsed cutover के रूप में देखें। नए सर्वर को शुरू से तैयार करें, डेटा को दो बार सिंक करें, और DNS को बदलने से पहले यह सुनिश्चित करें कि नया सर्वर अपने स्वयं के IP पते पर सही ढंग से काम कर रहा है। इसके बाद ही DNS रिकॉर्ड बदलें और पुराने सर्वर को तब तक चालू रखें जब तक आप पूरी तरह आश्वस्त न हो जाएं। बाइट्स को कॉपी करना आसान हिस्सा है। संचालन का क्रम ही यह तय करता है कि माइग्रेशन बिना किसी समस्या के होगा या महंगा साबित होगा।

यह गाइड एक Linux सर्वर को कवर करती है जिस पर एक वेब एप्लिकेशन, एक डेटाबेस और एक TLS (transport layer security) सर्टिफिकेट चल रहा है। यह अधिकांश सिंगल-सर्वर सेटअप के लिए पर्याप्त है। इसमें दो होस्ट शामिल हैं, इसलिए प्रत्येक उदाहरण में एक टिप्पणी के माध्यम से बताया गया है कि वह किस होस्ट पर चलता है। पते documentation ranges से लिए गए हैं: 198.51.100.10 पुराना सर्वर है, और 203.0.113.20 नया सर्वर है।

शुरू करने से पहले पूरा runbook पढ़ें। पहला चरण, DNS TTL को कम करना, उस चरण से कई दिन पहले किया जाना चाहिए जिसे आप वास्तव में पूरा करना चाहते हैं।

कुछ भी बनाने से पहले इन्वेंट्री तैयार करें

आप उस सर्वर को दोबारा नहीं बना सकते जिसका आपने विवरण नहीं लिखा है। पुराने सर्वर पर क्या-क्या चल रहा है, यह लिखने में एक घंटा लगाएँ, क्योंकि माइग्रेशन के बाद वही चीज़ खराब होती है जिसे कोई याद नहीं रखता: जैसे कि कोई cron job, firewall exception, या application directory के बाहर मौजूद कोई environment file।

पुराने सर्वर पर ये कमांड चलाएँ और आउटपुट को कहीं सुरक्षित रखें ताकि आप उसे नए सर्वर से देख सकें।

# old server: packages you asked for, not the dependencies they pulled in
apt-mark showmanual > ~/inv-packages.txt

# old server: what runs now, and what starts at boot
systemctl list-units --type=service --state=running --no-pager > ~/inv-services.txt
systemctl list-unit-files --state=enabled --no-pager >> ~/inv-services.txt
systemctl list-timers --all --no-pager > ~/inv-timers.txt

# old server: what is listening, on which address and port
sudo ss -tulpn > ~/inv-ports.txt

# old server: human accounts, skipping the system ones
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $6, $7}' /etc/passwd

apt-mark showmanual वह सूची है जो काम की है क्योंकि यह उन सभी पैकेजों को हटा देती है जो dependency के रूप में आए थे। पांच साल पुराने सर्वर पर पूर्ण dpkg --get-selections चलाने से दो हजार लाइनें मिलती हैं और यह आपके उद्देश्य के बारे में कुछ नहीं बताता।

Scheduled कार्य दो जगहों पर छिपे होते हैं, इसलिए दोनों की जाँच करें। जो काम महीने में केवल एक बार चलता है, वही वह काम है जिसे आप माइग्रेशन के छह सप्ताह बाद खोज पाएंगे।

# old server: per-user crontabs, then the system drop-ins
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -lu "$u" 2>/dev/null | sed "s/^/$u: /"; done
sudo ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly

इसके बाद वे हिस्से जो सामान्य फाइलें नहीं हैं: firewall rules, certificates, databases, और आप वास्तव में कितना डेटा स्थानांतरित कर रहे हैं।

# old server
sudo ufw status verbose        # or: sudo nft list ruleset
sudo certbot certificates
sudo -u postgres psql -c '\l'  # or: sudo mysql -e 'SHOW DATABASES;'
sudo du -xh --max-depth=1 / | sort -h

certbot certificates प्रत्येक certificate का नाम, उसके द्वारा कवर किए गए domains, उसकी समाप्ति तिथि और डिस्क पर फाइलों के paths को प्रिंट करता है। वह आउटपुट आपकी TLS चेकलिस्ट है। du -x एक ही filesystem पर रहता है, इसलिए यह किसी mounted backup volume में नहीं जाएगा और दस गुना बड़ी संख्या नहीं दिखाएगा।

दो चीजें सर्वर के बाहर रहती हैं और हर बार भुला दी जाती हैं। पहली, कोई भी third party जो आपके सर्वर के IP address को allowlist करती है: जैसे payment gateway, managed database, SMTP relay, या partner API। नए सर्वर का पता नया होता है, इसलिए cutover से पहले उन allowlists में नया IP जोड़ना आवश्यक है, बाद में नहीं। दूसरी, DNS रिकॉर्ड जो आपने स्वयं नहीं बनाए हैं, जैसे कि MX रिकॉर्ड या SPF रिकॉर्ड जिसमें टेक्स्ट में पुराना IP लिखा हो।

पुराने root filesystem को clone करने के बजाय उसे rebuild क्यों करें

पूरे root filesystem को नए VPS पर clone करना तेज लग सकता है, और यह तब तक तेज है जब तक कि कोई समस्या न आए। वर्षों से production में चल रहे root filesystem में ऐसी hand-edited configs होती हैं जिनका कोई documentation नहीं होता, ऐसे repositories के packages होते हैं जो अब मौजूद नहीं हैं, और पुराने platform के virtual hardware के लिए तैयार किया गया boot setup होता है। आप इन सभी को import कर लेते हैं, जिसमें वे कारण भी शामिल हैं जिनकी वजह से आप migration कर रहे थे।

Rebuild करना पहले दिन धीमा होता है, लेकिन उसके बाद हर दिन यह सस्ता पड़ता है। आप current release install करें, अपनी base hardening लागू करें, और फिर केवल data copy करें: application directory, site configs, database dump, certificates, और user uploads। जो कुछ भी आप समझा नहीं सकते, उसे न लाएं। नए box को उसी तरह शुरू करें जैसे आप किसी भी box को शुरू करते हैं, नए VPS पर पहले दस मिनट का पालन करें, फिर inventory से एक-एक करके services जोड़ें और अगली service जोड़ने से पहले प्रत्येक की पुष्टि करें।

कब image या snapshot restore का उपयोग करना सही है

rebuild करने के बजाय पुराने सर्वर को restore करना एक व्यावहारिक विकल्प है, लेकिन इसके लिए एक स्पष्ट स्थिति है। यदि पुराना सर्वर boot नहीं हो रहा है, या application ऐसी है जिसे अब source से rebuild नहीं किया जा सकता, तो provider image या snapshot restore ही सबसे सही समाधान है। इसकी वास्तविक सीमाएँ हैं: यह केवल एक ही provider के भीतर काम करता है, और अक्सर केवल एक ही plan family के अंदर, क्योंकि restore की गई disk उस platform के virtual devices और network naming की अपेक्षा करती है।

चलते हुए सर्वर का snapshot लेने पर वही consistency संबंधी समस्याएँ आती हैं जो किसी live database की file-level copy में होती हैं। image restore को migration plan के बजाय recovery का एक रास्ता मानें, और किसी भी योजना को अंतिम रूप देने से पहले snapshot और backup में अंतर क्यों होता है अवश्य पढ़ें।

फाइलें कैसे स्थानांतरित होती हैं: rsync over SSH

पुराने सर्वर से rsync चलाएं और डेटा को नए सर्वर पर पुश करें। पुश करना आमतौर पर सरल होता है, क्योंकि पुराने सर्वर में डेटा पहले से मौजूद होता है और वह sudo के तहत इसे पूरी तरह पढ़ सकता है।

# old server: dry run first, and read what it says it will do
sudo rsync -aHAX --dry-run --itemize-changes \
  -e 'ssh -i /root/.ssh/id_ed25519' \
  /srv/app/ deploy@203.0.113.20:/srv/app/

# old server: the real bulk pass
sudo rsync -aHAX --info=progress2 \
  -e 'ssh -i /root/.ssh/id_ed25519' \
  /srv/app/ deploy@203.0.113.20:/srv/app/

फ्लैग्स महत्वपूर्ण हैं। -a अनुमतियों (permissions), टाइमस्टैम्प, सिम्बॉलिक लिंक्स और ओनरशिप को सुरक्षित रखता है। -H हार्ड लिंक्स को अलग-अलग प्रतियों में बदलने के बजाय उन्हें हार्ड लिंक्स के रूप में ही रखता है। -A POSIX ACLs (एक्सेस कंट्रोल लिस्ट) को कॉपी करता है और -X विस्तारित विशेषताओं (extended attributes) को कॉपी करता है। यदि अंतिम दो का उपयोग न किया जाए, तो एक जैसी दिखने वाली फाइलें अलग तरह से व्यवहार कर सकती हैं, क्योंकि SELinux लेबल और ACLs विस्तारित विशेषताओं में ही रहते हैं और कोई अन्य चीज उन्हें रिकॉर्ड नहीं करती है।

दो विवरण यहाँ अधिकांश विफलताओं का कारण बनते हैं।

ट्रेलिंग स्लैश (trailing slash) यह तय करता है कि डेटा कहाँ जाएगा। /srv/app/ का अर्थ है उस डायरेक्टरी की सामग्री। /srv/app का अर्थ है स्वयं वह डायरेक्टरी। यदि आप इसमें गलती करते हैं, तो नए सर्वर पर /srv/app/app बन जाएगा, और एप्लिकेशन शुरू तो हो जाएगा लेकिन बाद में गायब फाइलों की रिपोर्ट देगा, क्योंकि जिन पाथ्स के साथ इसे कॉन्फ़िगर किया गया था, वे अब एक स्तर ऊपर चले गए हैं।

sudo के तहत, टिल्ड (tilde) root की होम डायरेक्टरी है। sudo rsync के अंदर -e 'ssh -i ~/.ssh/id_ed25519' लिखने पर की (key) को आपकी अपनी होम डायरेक्टरी के बजाय /root/.ssh में खोजा जाता है। यदि की वहाँ नहीं है, तो SSH Permission denied (publickey) प्रिंट करता है, rsync rsync: connection unexpectedly closed प्रिंट करता है और नॉन-जीरो एग्जिट कोड के साथ बंद हो जाता है। की पाथ को पूरा लिखें। यदि पाथ ठीक करने के बाद भी वह ऑथेंटिकेशन संदेश आता रहता है, तो publickey विफलता के कारणों की एक छोटी सूची है और नए सर्वर पर डायरेक्टरी अनुमतियाँ जाँचने के लिए अगला कदम हैं।

ओनरशिप के लिए एक निर्णय लेना आवश्यक है। root के रूप में चलाने पर, rsync डिफ़ॉल्ट रूप से ओनर और ग्रुप को नाम के आधार पर मैप करता है, इसलिए पुराने बॉक्स पर www-data के स्वामित्व वाली फाइल नए बॉक्स पर www-data के स्वामित्व में आ जाती है, भले ही संख्यात्मक UID (यूजर आईडी) अलग हो। रीबिल्ड के लिए आपको यही चाहिए। --numeric-ids को केवल तब जोड़ें जब आप ऐसे फाइलसिस्टम को कॉपी कर रहे हों जिसके अकाउंट्स टारगेट पर मौजूद नहीं हैं, और फिर ls -ln के साथ परिणाम की जाँच करें, क्योंकि बिना मैचिंग अकाउंट वाली UID के स्वामित्व वाली फाइल केवल एक संख्या के रूप में दिखाई देती है और इसे पढ़ने वाली हर सर्विस को एक्सेस से मना कर दिया जाता है।

बल्क पास को पुराने सर्वर के ट्रैफिक सर्व करने के दौरान ही, कुछ दिन पहले चलाएं। इसे जितनी बार चाहें दोहराएं: rsync केवल वही भेजता है जो बदला है, इसलिए दूसरा पास घंटों के बजाय मिनटों में पूरा हो जाता है। कटओवर विंडो के अंदर अंतिम पास में --delete जोड़ें ताकि पुराने सर्वर से हटाई गई फाइलें नए सर्वर से भी गायब हो जाएं।

# old server: final pass, inside the window, after the app has stopped writing
sudo rsync -aHAX --delete --info=progress2 \
  -e 'ssh -i /root/.ssh/id_ed25519' \
  /srv/app/ deploy@203.0.113.20:/srv/app/

--delete डेस्टिनेशन से उन फाइलों को हटा देता है जो सोर्स से हट चुकी हैं, इसलिए गलत सोर्स पाथ के साथ --delete का उपयोग करने पर डेस्टिनेशन डायरेक्टरी खाली हो सकती है। इसे हर बार पहले --dry-run के साथ चलाएं। लंबे ट्रांसफर तब भी रुक जाते हैं जब आपके लैपटॉप का SSH सेशन ड्रॉप हो जाता है, इसलिए उन्हें पुराने सर्वर पर tmux या screen के अंदर शुरू करें। यदि कॉपी करने के दौरान लिंक पूरी तरह भर जाता है और पुराना सर्वर अभी भी यूजर्स को सर्विस दे रहा है, तो --bwlimit=20M जोड़ें।

डेटाबेस को कैसे मूव करें: एक नेटिव डंप

डेटाबेस फाइलों की एक डायरेक्टरी नहीं होता है, भले ही वह वैसी दिखती हो। यह फाइलों का एक समूह है, साथ ही इन-मेमोरी स्टेट और एक write-ahead log है, जो केवल उन क्षणों में सुसंगत (consistent) होता है जिन्हें डेटाबेस स्वयं परिभाषित करता है। इसके लिए इसके अपने टूल का उपयोग करें।

PostgreSQL को दो डंप की आवश्यकता होती है, क्योंकि roles पूरे क्लस्टर के लिए होते हैं और pg_dump में वे शामिल नहीं होते हैं:

# old server
sudo -u postgres pg_dumpall --globals-only -f /var/backups/globals.sql
sudo -u postgres pg_dump -Fc -f /var/backups/appdb.dump appdb
# new server: restore in this order
sudo -u postgres psql -f /var/backups/globals.sql
sudo -u postgres createdb -O appuser appdb
sudo -u postgres pg_restore -d appdb --no-owner /var/backups/appdb.dump

globals.sql को छोड़ दें तो आपकी हर टेबल रिस्टोर हो जाएगी, लेकिन कोई भी एप्लिकेशन रोल उन्हें पढ़ नहीं पाएगा, क्योंकि GRANT स्टेटमेंट ऐसे यूजर को संदर्भित करते हैं जो मौजूद ही नहीं है। -Fc कस्टम आर्काइव फॉर्मेट में लिखता है, जिसे केवल pg_restore ही पढ़ सकता है और जो आपको बाद में चुनिंदा टेबल रिस्टोर करने की सुविधा देता है। इसे उसी मेजर वर्जन या उससे नए वर्जन में रिस्टोर करें। पुराने वर्जन में जाना, उदाहरण के लिए 17 से 16 में, समर्थित नहीं है, और pg_restore कुछ भी लिखने से पहले फाइल हेडर में unsupported-version एरर के साथ आर्काइव को रिजेक्ट कर देता है।

MySQL और MariaDB एक ही कमांड का उपयोग करते हैं, जिसमें चार ऐसे विकल्प होते हैं जो डिफ़ॉल्ट नहीं होते हैं:

# old server
sudo mysqldump --single-transaction --routines --triggers --events \
  --databases appdb > /var/backups/appdb.sql
# new server
sudo mysql < /var/backups/appdb.sql

--single-transaction राइटर्स को ब्लॉक किए बिना एक सुसंगत स्नैपशॉट लेता है, लेकिन केवल InnoDB टेबल के लिए। उसी डेटाबेस में मौजूद MyISAM टेबल को बिना किसी गारंटी के कॉपी किया जाता है, इसलिए डंप पर भरोसा करने से पहले अपने स्टोरेज इंजन की जांच करें। --routines, --triggers और --events डिफ़ॉल्ट रूप से बंद होते हैं, जिसका अर्थ है कि एक साधारण डंप आपके डेटा को तो रिस्टोर कर देगा, लेकिन चुपचाप आपके स्टोर्ड प्रोसीजर और शेड्यूल किए गए इवेंट्स को पीछे छोड़ देगा। डेटाबेस यूजर और उनके ग्रांट्स mysql सिस्टम डेटाबेस में रहते हैं, जिसे --databases appdb डंप कभी नहीं छूता है, इसलिए उन्हें नए सर्वर पर CREATE USER और GRANT के साथ फिर से बनाएं। MariaDB 11 वही टूल शिप करता है जो mariadb-dump करता है और mysqldump को एक सिम्बॉलिक लिंक के रूप में रखता है, इसलिए अगस्त 2026 तक दोनों में से कोई भी नाम काम करता है।

SQLite एक सिंगल फाइल है, और एप्लिकेशन के लिखते समय इसे कॉपी करने से फाइल करप्ट हो सकती है। इसका अपना सुरक्षित तरीका है:

# old server
sqlite3 /var/lib/app/app.db ".backup '/var/backups/app.db'"

इंजन चाहे जो भी हो, डंप पर भरोसा करने से पहले उसकी जांच करें। यदि डिस्क भर जाने के कारण डंप बीच में ही रुक गया था, तो वह बिना किसी चेतावनी के रिस्टोर हो जाएगा, लेकिन केवल उस बिंदु तक जहाँ तक वह अधूरा (truncated) था।

# old server: a complete mysqldump ends with a line reading "-- Dump completed on ..."
tail -n 3 /var/backups/appdb.sql

# new server: after restore, count rows in a table whose size you know
sudo mysql -e 'SELECT COUNT(*) FROM appdb.orders;'

आप चलते हुए database को rsync क्यों नहीं कर सकते

rsync फाइलों को एक-एक करके कॉपी करता है। एक चलता हुआ database एक साथ कई फाइलों में लिखता है, इसलिए जब तक rsync आखिरी फाइल तक पहुँचता है, तब तक पहली फाइल पुरानी हो चुकी होती है। इस कॉपी में अलग-अलग समय के डेटा पेज होते हैं, ऐसी स्थिति जो database में कभी थी ही नहीं। इसका परिणाम या तो यह होता है कि सर्वर start होने से मना कर देता है, या इससे भी बुरा: सर्वर start हो जाता है, एक हफ्ते तक सही जवाब देता है, और फिर तब फेल हो जाता है जब कोई query अंततः उस क्षतिग्रस्त पेज तक पहुँचती है। इस बीच कोई चेतावनी नहीं मिलती।

फाइलों को स्थानांतरित करने के दो सुरक्षित तरीके हैं। Database को stop करें, कॉपी करें, और फिर से start करें: यह सही और सरल है, और इसमें कॉपी करने की अवधि के बराबर downtime लगता है। या फिर उस टूल का उपयोग करें जो चलते हुए सर्वर की physical copy बनाने के लिए बनाया गया है। PostgreSQL के लिए वह pg_basebackup है, जो सर्वर के साथ समन्वय (coordinate) करता है ताकि कॉपी सुसंगत (consistent) रहे:

# new server: pull a physical copy from the old one
pg_basebackup -h 198.51.100.10 -U replicator -D /var/lib/postgresql/16/main -X stream -P

इसके लिए एक ऐसे role की आवश्यकता होती है जिसमें REPLICATION attribute हो और पुराने सर्वर पर एक मेल खाता हुआ pg_hba.conf entry हो, इसलिए यह dump की तुलना में अधिक सेटअप मांगता है। जब database इतना बड़ा हो कि dump और restore आपके निर्धारित समय (window) के भीतर पूरा न हो सके, तब यह उपयोगी होता है। एक सामान्य single-server migration के लिए, dump का उपयोग करना ही बेहतर है।

Cutover से पहले certificates को rebuild करें, बाद में नहीं

TLS certificate domain name से जुड़ा होता है, IP address से नहीं, इसलिए certificate file बिना किसी समस्या के move हो जाती है। जो चीज आसानी से move नहीं होती, वह है renewal। Certbot की default HTTP-01 challenge, certificate authority से कहती है कि वह port 80 के माध्यम से उस नाम पर एक file fetch करे जिसे certify किया जा रहा है। जब तक DNS नए सर्वर की ओर point नहीं करता, तब तक वह fetch पुराने सर्वर पर ही जाता है और नए सर्वर का renewal विफल हो जाता है।

पहला विकल्प मौजूदा certificates और उनकी renewal state को copy करना है। वे अपनी expiry date तक वैध रहते हैं, चाहे वे किसी भी सर्वर पर हों।

# old server
sudo rsync -aHAX -e 'ssh -i /root/.ssh/id_ed25519' \
  /etc/letsencrypt/ root@203.0.113.20:/etc/letsencrypt/

/etc/letsencrypt/renewal/ के अंतर्गत प्रत्येक file उस authenticator plugin का नाम बताती है जिसने certificate जारी किया था, इसलिए नए सर्वर पर भी वही plugin install करें (उदाहरण के लिए python3-certbot-nginx), अन्यथा पहला renewal ही unknown authenticator के संदेश के साथ विफल हो जाएगा। उस पर निर्भर होने से पहले यह सुनिश्चित करें कि renewal काम कर रहा है:

# new server, after DNS has moved
sudo certbot renew --dry-run

दूसरा विकल्प DNS-01 challenge का उपयोग करके नए सर्वर पर एक नया certificate जारी करना है। यह TXT record के माध्यम से नियंत्रण साबित करता है और port 80 को कभी touch नहीं करता। यह migration से पहले भी काम करता है, जब नाम अभी भी पुराने सर्वर पर ही resolve हो रहा होता है। यदि आप अपने DNS provider को automate कर सकते हैं, तो यह अधिक बेहतर विकल्प है। DNS-01 challenge के साथ certificates जारी करना में plugin और credential setup की जानकारी दी गई है।

दोनों ही स्थितियों में, DNS बदले बिना यह जाँचें कि नया सर्वर वास्तव में क्या प्रस्तुत कर रहा है:

# your laptop
echo | openssl s_client -connect 203.0.113.20:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -dates -issuer

-servername, SNI (server name indication) भेजता है, जो web server को सही virtual host चुनने में मदद करता है। यदि आप इसे हटा देते हैं, तो आपको उस IP के लिए default certificate मिलेगा और एक mismatch दिखाई देगा, जो एक वास्तविक समस्या लग सकती है लेकिन वास्तव में ऐसा नहीं है।

Cutover से कई दिन पहले DNS TTL को कम करें

DNS वह जगह है जहाँ सावधानीपूर्वक की गई migration भी गलत हो सकती है, क्योंकि इसमें delay पहले से ही शामिल होता है और आप इसे cutover वाले दिन कम नहीं कर सकते। एक resolver जिसने आपके A record को cache किया है, वह उसे TTL (time to live) की अवधि तक serve करना जारी रखता है। TTL को अभी कम करने से उस resolver को कोई लाभ नहीं होगा जिसने 10 मिनट पहले पुराने मान के साथ record cache किया था: वह पुराने TTL की शेष अवधि तक पुराने मान को ही रखेगा और उसके बाद ही नया, छोटा मान प्राप्त करेगा। इसलिए, cutover से कम से कम एक पूर्ण पुराने-TTL अवधि पहले TTL को कम करें। एक दिन पहले का समय सुरक्षित रहता है। यदि ये प्रक्रियाएं आपके लिए नई हैं, तो records, resolvers और caching का walkthrough बुनियादी जानकारी प्रदान करता है।

नीचे दिए गए आंकड़े TTL से प्राप्त गणितीय गणना हैं, न कि कोई मापन।

ChartHow long a stale IP can survive, by record TTL
The data behind this chart
[
  {
    "label": "TTL 3600 s (common default)",
    "ttl_seconds": 3600,
    "worst_case_stale_minutes": 60
  },
  {
    "label": "TTL 900 s",
    "ttl_seconds": 900,
    "worst_case_stale_minutes": 15
  },
  {
    "label": "TTL 300 s (lowered for cutover)",
    "ttl_seconds": 300,
    "worst_case_stale_minutes": 5
  },
  {
    "label": "TTL 60 s (short window)",
    "ttl_seconds": 60,
    "worst_case_stale_minutes": 1
  }
]

3600 seconds के TTL के साथ प्रकाशित एक A record, आपके द्वारा इसे बदलने के बाद भी 60 minutes तक users को पुराने IP पर भेज सकता है। इसे घटाकर 300 seconds करने पर यह worst case घटकर 5 minutes रह जाता है। इन आंकड़ों को एक गारंटी के बजाय न्यूनतम सीमा मानें। कुछ resolvers अपना स्वयं का न्यूनतम TTL लागू करते हैं और इससे कम किसी भी मान को अनदेखा कर देते हैं, और कुछ application runtimes resolved address को process के जीवनकाल तक cache करते हैं। इसलिए, जो client आपके बदलाव से पहले शुरू हुआ था, वह restart होने तक दोबारा DNS lookup नहीं कर सकता है।

जब आप यह जाँचें कि कम किया गया TTL live है, तो अपने स्वयं के cache के बजाय authoritative उत्तर देखें:

# your laptop: ask the zone's own nameserver, so no cache is involved
dig +short NS example.com
dig +noall +answer @$(dig +short NS example.com | head -n1) example.com A

उस उत्तर पंक्ति का दूसरा field seconds में TTL है। इसके बाद उन records को देखें जिन्हें लोग अक्सर भूल जाते हैं: AAAA record (यदि पुराने server में IPv6 था), www नाम (जब यह CNAME के बजाय एक अलग A record हो), server की ओर इशारा करने वाला कोई भी MX record, पुराने IP को सूचीबद्ध करने वाला SPF record, और नए address पर reverse DNS (PTR) record। यदि server mail भेजता है, तो cutover से पहले अपने provider के control panel के माध्यम से PTR set करें, क्योंकि receiving mail servers इसकी जाँच करते हैं और PTR न होने पर बाकी सब कुछ ठीक दिखने के घंटों बाद भी mail reject हो सकती है।

DNS बदलने से पहले नए सर्वर को उसके IP पर सत्यापित करें

आप DNS के पुराने सर्वर पर पॉइंट करते समय भी नए सर्वर पर पूरे एप्लिकेशन का परीक्षण कर सकते हैं। एक अनुरोध के लिए नेम लुकअप को ओवरराइड करें:

# your laptop: force one name to the new IP, for this request only
curl -sS --resolve example.com:443:203.0.113.20 \
  -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://example.com/

--resolve केवल यह बदलता है कि कनेक्शन कहाँ जाता है। TLS सर्टिफिकेट की जाँच अभी भी वास्तविक नाम के आधार पर की जाती है, इसलिए यह सर्टिफिकेट और सर्विस दोनों को प्रमाणित करता है। %{ssl_verify_result} जब चेन सत्यापित हो जाती है तो 0 प्रिंट करता है।

ब्राउज़र में साइट को क्लिक करके देखने के लिए, अपने लैपटॉप पर /etc/hosts में या Windows पर C:\Windows\System32\drivers\etc\hosts में एक लाइन जोड़कर अपनी पूरी मशीन के लिए नाम को ओवरराइड करें:

203.0.113.20 example.com www.example.com

फिर एप्लिकेशन को वैसे ही चलाएँ जैसे एक उपयोगकर्ता चलाएगा। लॉग इन करें। डेटाबेस से पढ़ने वाला पेज लोड करें। डेटाबेस में लिखने वाला फॉर्म सबमिट करें। एक फाइल अपलोड करें और पुष्टि करें कि वह डिस्क पर पहुँच गई है। जो भी ईमेल भेजता है उसे ट्रिगर करें, और जाँचें कि वह प्राप्त हुआ है या नहीं, क्योंकि नए IP से आउटबाउंड SMTP अक्सर आश्चर्यचकित कर सकता है। काम पूरा होते ही hosts लाइन को हटा दें। इसे वहीं छोड़ देने से आप एक घंटा ऐसी साइट को डीबग करने में बिता सकते हैं जिसे बाकी सभी लोग बिल्कुल सही देख पा रहे हैं।

Cutover की चरण-दर-चरण प्रक्रिया

  1. कुछ दिन पहले: TTL कम करें, bulk rsync चलाएं, नया सर्वर तैयार करें और hosts override के माध्यम से उसका परीक्षण करें।
  2. निर्धारित दिन, window से पहले: नए IP को सभी third-party allowlist में जोड़ें, और सुनिश्चित करें कि नए सर्वर का backup job कॉन्फ़िगर है और आपके repository की ओर निर्देशित है।
  3. Window खोलें: पुराने सर्वर पर application को maintenance mode में डालें ताकि वह writes स्वीकार करना बंद कर दे।
  4. अंतिम database dump लें, फिर --delete के साथ अंतिम rsync पास चलाएं।
  5. नए सर्वर पर dump को restore करें और services शुरू करें।
  6. --resolve और hosts override के माध्यम से पुनः परीक्षण करें, जिसमें एक वास्तविक write भी शामिल हो।
  7. A और AAAA records को नए IP पर बदलें।
  8. दोनों सर्वरों पर नज़र रखें। पुराने सर्वर का access log दिखाता है कि कौन अभी भी वहां आ रहा है, और TTL के दौरान यह संख्या शून्य की ओर आ जानी चाहिए।
  9. Maintenance page हटाएं।
  10. पुराने सर्वर को कम से कम एक सप्ताह तक चालू और यथावत रहने दें।

Maintenance mode वाला चरण वह है जिसे लोग छोड़ देते हैं, और यही वह चरण है जो आपकी सुरक्षा करता है। एक बार जब नए database ने write स्वीकार कर लिया, तो rollback करने का अर्थ है या तो उस write को खोना या नए database को dump करके उसे पुराने में वापस load करना। कुछ मिनटों की read-only window सस्ती पड़ती है। दो databases जिनमें दोनों में writes हुए हों, उन्हें ठीक करने में दिनों का manual काम लग सकता है।

रोलबैक योजना

रोलबैक केवल एक क्रिया है: DNS रिकॉर्ड्स को वापस 198.51.100.10 पर बदलें। यह केवल उन चार चीजों के कारण काम करता है जो आपने पहले की थीं।

  • पुराना सर्वर अभी भी चल रहा है, उसकी services active हैं और डेटा सुरक्षित है। आपने वहां writes बंद किए थे, उसे decommission नहीं किया था।
  • TTL अभी भी कम है, इसलिए वापसी का रास्ता उतना ही तेज़ है जितना आगे बढ़ने का था।
  • आपने पुराने IP को हटाने के बजाय नए IP को third-party allowlists में जोड़ा था। यदि आप पुराना पता हटा देते हैं, तो payment gateway पर आपका रोलबैक विफल हो जाएगा।
  • नए सर्वर पर ऐसा कोई write नहीं हुआ है जिसे आप पहचान न सकें, क्योंकि अब तक केवल आपके द्वारा किए गए test transactions ही हुए हैं।

विंडो खुलने से पहले तय करें कि रोलबैक कब करना है। दो ट्रिगर पर्याप्त हैं: कोई भी ऐसी त्रुटि जिसे आप निश्चित मिनटों के भीतर डायग्नोस नहीं कर सकते, और किसी भी प्रकार का डेटा लॉस। इन्हें पहले से लिख लेना ही उस घंटों के अनुमान को रोकता है जो दस मिनट के आउटेज को एक लंबे आउटेज में बदल देता है।

प्रमाणित करें कि माइग्रेशन सफल रहा

माइग्रेशन तब पूरा नहीं होता जब साइट लोड होने लगती है। उन चीजों की जाँच करें जो केवल बाद में विफल होती हैं।

# new server
systemctl --failed
journalctl -p err -b --no-pager | tail -n 40
sudo certbot certificates
sudo systemctl list-timers --all --no-pager

systemctl --failed रिपोर्टिंग 0 loaded units listed वह परिणाम है जो आप चाहते हैं। certbot certificates को आपकी अपेक्षित समाप्ति तिथियाँ दिखानी चाहिए, और list-timers को आपकी इन्वेंट्री से प्रत्येक निर्धारित कार्य (scheduled job) को एक वास्तविक 'अगली बार चलने के समय' (next-run time) के साथ दिखाना चाहिए, न कि खाली।

इसके बाद, नए सर्वर को जानबूझकर एक बार रीबूट करें, जबकि आप उसे देख रहे हों। कोई ऐसी सर्विस जिसे किसी ने मैन्युअल रूप से शुरू किया हो और कभी enable न किया हो, वह सुबह तीन बजे होने वाले पहले अनियोजित रीबूट तक बिल्कुल सही काम करती है।

# new server
sudo reboot

# your laptop, once it comes back
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com/

यदि एप्लिकेशन कंटेनरों में चलता है, तो यही समस्या एक अलग रूप ले लेती है, क्योंकि एक compose stack को रीबूट के बाद वापस आने के लिए एक स्पष्ट restart policy की आवश्यकता होती है

अंतिम जाँच को टालना सबसे आसान है और यही सबसे महत्वपूर्ण भी है: बैकअप जॉब। एक माइग्रेशन जो बिना बैकअप वाले सर्वर पर समाप्त होता है, उसने एक जोखिम को दूसरे जोखिम से बदल दिया है। नए सर्वर पर मैन्युअल रूप से बैकअप चलाएँ, फिर उससे एक फाइल को अस्थायी डायरेक्टरी में रिस्टोर करें। एक restic रिपॉजिटरी जिसका रिस्टोर आपने वास्तव में टेस्ट किया है, वही संस्करण है जो जरूरत पड़ने पर आपकी मदद करता है। यदि आप पुराने और नए सर्वर को एक सप्ताह तक साथ-साथ चला रहे हैं, तो प्रत्येक होस्ट तक पहुँचने और उसे कॉन्फ़िगर करने का एक सुसंगत तरीका दोनों को अलग होने से रोकता है जबकि वे दोनों लाइव हों।

कटओवर के बाद: पुराना सर्वर और अंतिम कार्य

पुराने सर्वर को एक से दो सप्ताह तक बनाए रखें। इसकी लागत आपके द्वारा रद्द किए जाने वाले प्लान के एक महीने के शुल्क के बराबर है, और यह आपके पास उपलब्ध एकमात्र रोलबैक विकल्प है। इसके बाद बाकी चीजों को समाप्त करें।

  • अपने ~/.ssh/config में उसी hostname का पुन: उपयोग करने पर पहली बार कनेक्ट करते समय आपको WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! मिलेगा, क्योंकि अब वह नाम एक अलग host key के साथ प्रतिक्रिया देता है। जब आप सुनिश्चित हो जाएं कि यह बदलाव क्यों हुआ है, तभी ssh-keygen -R example.com का उपयोग करके पुरानी एंट्री को हटाएँ। इसे बिना सोचे-समझे न करें, क्योंकि यही चेतावनी एक इंटरसेप्शन अटैक के दौरान भी दिखाई देती है। माइग्रेशन का समय यह समीक्षा करने के लिए भी अच्छा है कि कौन सी keys कहाँ तक पहुँच सकती हैं, जिसके लिए छोटे फ्लीट पर SSH key प्रबंधन का उपयोग किया जाता है।
  • पुराने सर्वर का एक अंतिम स्नैपशॉट या बैकअप लें, और इसे किसी ऐसे स्थान पर स्टोर करें जो पुराने प्रदाता का हिस्सा न हो।
  • पुराने IP को मॉनिटरिंग चेक, SPF रिकॉर्ड्स और थर्ड-पार्टी अलाउलिस्ट से इसी क्रम में और सबसे अंत में हटाएँ।
  • पुराने प्लान को केवल तभी रद्द करें जब उस अंतिम कॉपी के कहीं और पठनीय होने की पुष्टि हो जाए।

FAQ

एक सर्वर को नए VPS पर migrate करने में कितना समय लगता है?

उपयोगकर्ता को दिखने वाला outage आमतौर पर अंतिम database dump, अंतिम rsync पास और service start तक सीमित होता है, इसलिए एक छोटे application के लिए इसमें दस से तीस मिनट लगते हैं। कैलेंडर का समय अधिक होता है, क्योंकि DNS TTL को स्विच करने से पहले कम से कम एक पुराने-TTL अवधि के लिए कम करना पड़ता है और एक दिन पहले ऐसा करना अधिक सुरक्षित है। बल्क डेटा कॉपी की योजना भी कुछ दिन पहले ही बना लें। यह एक live सर्वर पर चलता है, और बाद में इसे दोहराने पर केवल वही डेटा transfer होता है जो पिछले पास के बाद बदला है।

क्या मैं dump करने के बजाय चल रहे MySQL या PostgreSQL database को rsync कर सकता हूँ?

नहीं। rsync फाइल-दर-फाइल कॉपी करता है जबकि database एक साथ कई फाइलों में लिख रहा होता है, इसलिए कॉपी में अलग-अलग समय के पेज होते हैं और यह ऐसी स्थिति को दर्शाता है जो database में कभी थी ही नहीं। यह start होने से मना कर सकता है, या start होकर बाद में विफल हो सकता है जब कोई query किसी क्षतिग्रस्त पेज तक पहुँचती है। pg_dump के साथ pg_dumpall --globals-only, या mysqldump --single-transaction का उपयोग करें, या पहले database को रोकें और फिर फाइलें कॉपी करें। एक बड़े PostgreSQL cluster के लिए, pg_basebackup एक चल रहे सर्वर की सुसंगत physical कॉपी बनाता है।

DNS बदलने से पहले मैं नए VPS का परीक्षण कैसे करूँ?

अपनी मशीन पर name lookup को override करें। एक single request के लिए, curl --resolve example.com:443:203.0.113.20 https://example.com/ कनेक्शन को नए IP पर भेजता है जबकि certificate को वास्तविक नाम के विरुद्ध जांचता रहता है। ब्राउज़र परीक्षण के लिए, अपने लैपटॉप पर /etc/hosts में 203.0.113.20 example.com जोड़ें, login, database read, form write और file upload का परीक्षण करें, फिर उस लाइन को हटा दें। केवल certificate का निरीक्षण करने के लिए, openssl s_client -connect 203.0.113.20:443 -servername example.com चलाएँ।

मुझे क्या TTL सेट करना चाहिए, और इसे कब कम करना चाहिए?

A और AAAA records को 300 seconds पर कम करें, और इसे cutover से कम से कम एक पूर्ण पुराने-TTL अवधि पहले करें। जो resolver आपके बदलाव से पहले record को cache कर चुका है, वह पुराने TTL की शेष अवधि के लिए पुराने मान को ही रखता है, इसलिए यदि पुराना TTL 86400 था तो एक घंटे पहले इसे कम करने का कोई लाभ नहीं है। migration के कुछ दिन बाद, जब पुराने सर्वर का access log शांत हो जाए, तो इसे वापस अपने सामान्य मान पर सेट कर दें।

क्या मुझे TLS certificate कॉपी करना चाहिए या नए सर्वर पर नया जारी करना चाहिए?

दोनों तरीके काम करते हैं। /etc/letsencrypt/ को कॉपी करने से certificate अपनी मौजूदा समाप्ति तिथि तक वैध रहता है, लेकिन आपको नए सर्वर पर वही certbot authenticator plugin इंस्टॉल करना होगा अन्यथा पहला renewal विफल हो जाएगा, इसलिए पुष्टि करने के लिए DNS स्विच के बाद certbot renew --dry-run चलाएँ। जब आप DNS-01 challenge का उपयोग कर सकते हैं तो नया certificate जारी करना अधिक साफ-सुथरा होता है, क्योंकि यह TXT record के माध्यम से नियंत्रण साबित करता है और DNS के नए सर्वर पर पॉइंट होने से पहले ही काम करता है। HTTP-01 challenge का उपयोग नए सर्वर पर तब तक नहीं किया जा सकता जब तक DNS स्थानांतरित न हो जाए, क्योंकि validation request पुराने सर्वर तक पहुँच जाएगी।