SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor

آموزش پشتیبان‌گیری از VPS با Restic و انتقال به سرور دیگر

با استفاده از Restic از داده‌های VPS خود نسخه پشتیبان رمزنگاری‌شده و deduplicated تهیه کنید. این راهنما نحوه تنظیم خودکار در Ubuntu 24.04 و بازیابی امن را آموزش می‌دهد.

چرا نسخه پشتیبان روی همان سرور، نسخه پشتیبان محسوب نمی‌شود

Restic یک ابزار پشتیبان‌گیری رایگان و متن‌باز است که اسنپ‌شات‌های رمزنگاری‌شده و حذف‌تکرار (deduplicated) از فایل‌های شما را به یک مخزن در مکانی دیگر ارسال می‌کند: یک VPS دوم، یک دستگاه در خانه، یا فضای ذخیره‌سازی شیء (object storage) سازگار با S3. این راهنما نحوه راه‌اندازی آن روی Ubuntu 24.04 را از مرحله نصب تا ایجاد مخزن روی SFTP، اولین پشتیبان‌گیری، تنظیم تایمر nightly در systemd، سیاست نگهداری (retention policy) و تمرین بازیابی که صحت کل فرآیند را اثبات می‌کند، پوشش می‌دهد. مقصد باید دستگاه دیگری باشد، زیرا نسخه‌ای که روی همان سرور قرار دارد، با از بین رفتن سرور از دست می‌رود.

یک دایرکتوری backup/ روی همان دستگاهی که از آن پشتیبان تهیه می‌شود، تنها شما را در برابر یک مورد محافظت می‌کند: حذف تصادفی یک فایل. این نسخه در صورت خرابی دیسک باقی نمی‌ماند، زیرا روی همان دیسک قرار داشته است. در برابر مهاجمی با دسترسی root نیز مقاوم نیست، زیرا آن‌ها ابتدا نسخه‌های پشتیبان را حذف می‌کنند. همچنین در برابر اشتباهات کاربری که منجر به حذف خودِ VPS شود، کارایی ندارد. کم‌بازده‌ترین دیتاسنتر جهان به یک فایل tarball با نام backup_final_v2_REAL که روی همان آرایه دیسکِ داده‌های اصلی قرار دارد، کنایه می‌زند؛ این شوخی به این دلیل خنده‌دار است که بسیاری از ما دقیقاً همین کار را انجام داده‌ایم. قانون اصلی این است که پشتیبان باید خارج از دستگاه باشد و restic کم‌دردسرترین راه برای رعایت این قانون است.

Restic در چهار ایده

مخزن (Repository). مکانی که restic داده‌ها را در آن می‌نویسد. این یک دایرکتوری با فرمت اختصاصی restic است که مملو از بلاک‌های رمزنگاری‌شده است و فقط restic می‌تواند آن را بخواند. شما هرگز نباید آن را به‌صورت دستی ویرایش کنید؛ تعامل با آن فقط از طریق دستورات restic و آدرس -r انجام می‌شود.

اسنپ‌شات (Snapshot). تصویری از فایل‌های پشتیبان‌گیری‌شده در یک لحظه خاص. هر بار اجرای عملیات پشتیبان‌گیری، یک اسنپ‌شات ایجاد می‌کند. هر اسنپ‌شات به‌تنهایی قابل بازیابی است و مانند یک کپی کامل از داده‌های شما در آن لحظه عمل می‌کند.

حذف داده‌های تکراری (Deduplication). ابزار restic فایل‌ها را به تکه‌هایی بر اساس محتوا تقسیم کرده و فقط تکه‌هایی را آپلود می‌کند که در مخزن وجود ندارند. اولین پشتیبان‌گیری همه چیز را آپلود می‌کند؛ اما هر اجرای بعدی فقط تغییرات را آپلود می‌کند. یک اسنپ‌شات شبانه 20 گیگابایتی که 50 مگابایت تغییر داشته، فقط 50 مگابایت فضا اشغال می‌کند؛ به همین دلیل نگهداری ده‌ها اسنپ‌شات بسیار کم‌هزینه است.

رمزنگاری پیش‌فرض. مخزن restic همیشه رمزنگاری‌شده (AES-256) است. Restic از ایجاد یا باز کردن مخزن با رمز عبور خالی خودداری می‌کند، مگر اینکه از فلگ --insecure-no-password استفاده کنید (در restic نسخه 0.17.0 و بالاتر). بنابراین، مخزنی که طبق این راهنما تنظیم شده، برای هر دستور به رمز عبور نیاز دارد. میزبان پشتیبان یا ارائه‌دهنده فضای ذخیره‌سازی، فقط بلاک‌های رمزنگاری‌شده را می‌بیند. نتیجه قطعی این است: اگر رمز عبور را گم کنید، داده‌ها برای همیشه و طبق طراحی سیستم از دست می‌روند. یک کپی از رمز عبور را در جایی غیر از این سرور نگهداری کنید. این موضوع آن‌قدر مهم است که در ادامه دو بار دیگر به آن اشاره می‌شود.

نصب restic روی Ubuntu 24.04

sudo apt update && sudo apt install -y restic
restic version

در Ubuntu 24.04، این دستور نسخه 0.16.4 از restic را نصب می‌کند، در حالی که نسخه فعلی upstream برابر با 0.19.1 است. این فاصله به این دلیل است که نسخه‌های LTS (پشتیبانی بلندمدت) نسخه‌های بسته‌های خود را ثابت نگه می‌دارند، اما این موضوع در اینجا اهمیتی ندارد: نسخه 0.16.4 تمام نیازهای این راهنما را پوشش می‌دهد. اگر به دلیل بهبودهای سرعت به جدیدترین نسخه نیاز دارید، فایل باینری رسمی را از صفحه GitHub releases پروژه restic دانلود کنید، آن را با bunzip2 استخراج کرده و در /usr/local/bin/restic نصب کنید؛ نصب restic پیچیدگی دیگری ندارد.

ایجاد مخزن روی سروری دیگر از طریق SFTP

شما به یک ماشین مقصد نیاز دارید: یک VPS کوچک دوم معمولاً بهترین گزینه است و هر سیستمی که دارای SSH server و فضای دیسک کافی باشد، کارآمد است. Restic از پروتکل SFTP (انتقال فایل روی SSH) استفاده می‌کند، بنابراین میزبان پشتیبان به هیچ نرم‌افزار خاصی نیاز ندارد. در این راهنما، میزبان پشتیبان 10.0.0.12 است و کاربری با نام restic دارد. آن کاربر را backup نام‌گذاری نکنید: توزیع‌های Ubuntu و Debian در هر نصب، یک حساب سیستمی رزرو شده به نام backup (با uid 34 و بدون login shell) دارند، بنابراین adduser backup با شکست مواجه می‌شود و ssh backup@... در nologin قرار می‌گیرد.

وظیفهٔ شبانه (nightly job) به عنوان root روی سروری که از آن پشتیبان گرفته می‌شود اجرا خواهد شد، بنابراین root برای ورود به میزبان پشتیبان به کلید نیاز دارد. یک کلید اختصاصی بدون passphrase بسازید، زیرا در ساعت 3 بامداد هیچ انسانی برای وارد کردن آن حضور ندارد، سپس آن را کپی کنید:

sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N "" -C "web1-restic"
sudo ssh-copy-id -i /root/.ssh/id_ed25519.pub restic@10.0.0.12
sudo ssh restic@10.0.0.12 true && echo key login works

اگر با کلیدها آشنا نیستید، اصول مدیریت کلید SSH مدل، مجوزها و نحوهٔ ابطال کلید در آینده را توضیح می‌دهد.

سپس، رمز عبور مخزن را تعیین کنید. یک رمز قوی تولید کرده و آن را در فایلی که فقط برای root قابل خواندن است ذخیره کنید:

openssl rand -base64 32 | sudo tee /root/.restic-password
sudo chmod 600 /root/.restic-password

اکنون پیش از ادامه، آن رمز عبور را در مدیریت رمزهای خود کپی کنید. اگر این VPS از بین برود، مخزن به همراه این رمز عبور همه چیز را بازیابی می‌کند؛ مخزن بدون رمز عبور هیچ چیزی را بازیابی نخواهد کرد.

مخزن را مقداردهی اولیه کنید:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password init
created restic repository 9f3c2a1b0d at sftp:restic@10.0.0.12:/srv/restic/web1

مقصد جایگزین، فضای ذخیره‌سازی شیء (object storage) سازگار با S3 است که وقتی نمی‌خواهید ماشین دومی را مدیریت کنید، انتخاب مناسبی است. هر bucket سازگار با S3 به همان روش کار می‌کند؛ فقط آدرس و دو متغیر اعتبارنامه تغییر می‌کنند:

export AWS_ACCESS_KEY_ID=your-key-id
export AWS_SECRET_ACCESS_KEY=your-secret-key
sudo -E restic -r s3:https://s3.example.com/web1-backups --password-file /root/.restic-password init

همه چیز بعد از init برای هر دو مقصد یکسان است. بقیهٔ این راهنما آدرس SFTP را نشان می‌دهد؛ آدرس خود را جایگزین کنید.

اولین نسخه پشتیبان، همراه با موارد مستثنی‌شده

از داده‌هایی که امکان نصب مجدد آن‌ها را ندارید نسخه پشتیبان تهیه کنید، نه از کل سیستم فایل. سیستم‌عامل با نصب مجدد بازمی‌گردد؛ اما پیکربندی و داده‌های شما خیر. برای یک VPS معمولی، این شامل /etc، /home و هر مسیری است که برنامه‌های شما وضعیت (state) خود را در آن نگه می‌دارند، مانند /srv یا /var/www. کش‌ها را مستثنی کنید، زیرا حجم آن‌ها زیاد است، روزانه تغییر می‌کنند و خودبه‌خود بازسازی می‌شوند:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password backup /etc /home /srv --exclude '/home/*/.cache'
Files:        4181 new,     0 changed,     0 unmodified
Added to the repository: 731.204 MiB (312.418 MiB stored)
snapshot 5b8a3f2c saved

اجرای اول همه چیز را آپلود می‌کند، بنابراین مدتی طول می‌کشد. همان دستور را دوباره اجرا کنید تا در عرض چند ثانیه به پایان برسد؛ این دستور گزارش می‌دهد که چند فایل تغییر کرده و چند MiB اضافه شده است، زیرا deduplication فقط تکه‌های جدید را آپلود می‌کند. لیست موارد موجود را مشاهده کنید:

sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password snapshots

هر snapshot یک شناسه، زمان و مسیرهایی که شامل می‌شود را نشان می‌دهد. این شناسه‌ها همان مواردی هستند که از طریق آن‌ها بازیابی (restore) را انجام می‌دهید.

اجرای شبانه با استفاده از systemd timer

تایپ کردن آدرس مخزن در هر دستور خسته‌کننده است و پشتیبان‌گیری دستی معمولاً پس از یک ماه فراموش می‌شود. هر دو مشکل با یک اسکریپت و یک تایمر حل می‌شوند. این اسکریپت دو متغیر محیطی که restic می‌خواند، یعنی RESTIC_REPOSITORY و RESTIC_PASSWORD_FILE را تنظیم می‌کند تا هر دستوری در داخل آن کوتاه باقی بماند:

sudo nano /usr/local/bin/restic-backup.sh
#!/usr/bin/env bash
set -euo pipefail
export RESTIC_REPOSITORY='sftp:restic@10.0.0.12:/srv/restic/web1'
export RESTIC_PASSWORD_FILE=/root/.restic-password

restic backup /etc /home /srv --exclude '/home/*/.cache'
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
sudo chmod 700 /usr/local/bin/restic-backup.sh

خطوط forget و check در دو بخش بعدی توضیح داده شده‌اند. حالا نوبت زمان‌بندی است: یک سرویس oneshot که اسکریپت را اجرا می‌کند و یک تایمر که آن را هر شب ساعت 03:00 فعال می‌سازد. در اینجا تایمر از cron بهتر عمل می‌کند، زیرا خروجی اجرا در journal ثبت می‌شود و Persistent=true پشتیبان‌گیریِ از دست رفته را بلافاصله پس از بالا آمدن سرور بعد از قطعی، اجرا می‌کند.

# /etc/systemd/system/restic-backup.service
[Unit]
Description=Nightly restic backup
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/restic-backup.sh
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run the nightly restic backup

[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=15m
Persistent=true

[Install]
WantedBy=timers.target

تایمر را فعال کنید، سپس سرویس را یک بار به‌صورت دستی اجرا کنید و عملکرد آن را مشاهده نمایید:

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
sudo systemctl start restic-backup.service
sudo journalctl -u restic-backup.service -f

دستور systemctl list-timers زمان اجرای بعدی را نشان می‌دهد. شما همچنین می‌توانید به‌جای تایپ کردن فایل‌های unit، آن‌ها را تولید کنید:

ToolGenerate the backup service and timer

الگوی کامل این دو فایل، شامل سینتکس تقویمی و دستورالعمل‌های امنیتی که یک سرویس می‌تواند داشته باشد، در اجرای یک برنامه به عنوان سرویس systemd روی VPS آمده است.

پشتیبان‌گیری تا زمان بازیابی، فقط یک شایعه است

این جمله را به عنوان یک دستورالعمل قطعی در نظر بگیرید. کاری که هر شب با موفقیت اجرا می‌شود، فقط ثابت می‌کند که عملیات انجام شده است؛ نه اینکه داده‌های شما قابل بازگشت هستند. دو بررسی این شکاف را پر می‌کند.

نخست، restic check که اسکریپت از قبل آن را به‌صورت شبانه اجرا می‌کند. این دستور ساختار مخزن و ایندکس را بررسی می‌کند تا خرابی‌های پنهان در میزبان پشتیبان، به‌جای روز بازیابی، در همان شب شناسایی شوند. ماهی یک‌بار، نسخه دقیق‌تر را اجرا کنید که یک‌دهم داده‌های واقعی را دانلود و به‌صورت رمزنگاری‌شده تأیید می‌کند:

sudo -i
export RESTIC_REPOSITORY='sftp:restic@10.0.0.12:/srv/restic/web1'
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic check --read-data-subset=10%

از آنجا که این زیرمجموعه هر بار به‌صورت تصادفی انتخاب می‌شود، مستندات restic تأکید می‌کنند که اجرای مکرر تضمین نمی‌کند تمام فایل‌های pack بررسی شوند. اگر می‌خواهید بررسی‌های ماهانه بدون نیاز به دانلود کامل، کل مخزن را پوشش دهند، از فرم گروه ثابت استفاده کنید: --read-data-subset=1/10 در یک ماه، 2/10 در ماه بعد و به همین ترتیب تا 10/10. Restic فایل‌های pack را به ده گروه تقریباً مساوی تقسیم کرده و فقط گروه n را بررسی می‌کند؛ بنابراین یک چرخه کامل ده ماهه، تمام گروه‌ها را یک‌بار بررسی می‌کند.

دوم، تمرین بازیابی. همچنان در shell ریشه (root) که از قبل باز است، یک دایرکتوری واقعی را از آخرین اسنپ‌شات به یک مکان موقت بازیابی کرده و آن را با فایل‌های زنده مقایسه کنید:

restic restore latest --target /srv/restore-drill --include /etc/ssh
diff -r /etc/ssh /srv/restore-drill/etc/ssh

اگر diff هیچ خروجی‌ای چاپ نکرد، یعنی هر بایت دقیقاً بازیابی شده است؛ این تنها مدرکی است که اعتبار دارد. پس از آن /srv/restore-drill را حذف کنید. این تمرین را ماهانه انجام دهید و یک یا دو بار در سال نسخه کامل آن را اجرا کنید: کل آخرین اسنپ‌شات را روی یک VPS موقت بازیابی کنید و مطمئن شوید که برنامه شما واقعاً از روی آن اجرا می‌شود. روزی که تحت فشار نیاز به این کار دارید، می‌خواهید این فرآیندی باشد که قبلاً بارها انجام داده‌اید.

نگهداری: forget و prune

بدون وجود یک سیاست مشخص، اسنپ‌شات‌ها برای همیشه انباشته شده و حجم مخزن (repository) مدام افزایش می‌یابد. خط forget در اسکریپت، هر شب یک سیاست را اعمال می‌کند: --keep-daily 7 یک اسنپ‌شات برای هر روز در 7 روز گذشته، --keep-weekly 4 یک اسنپ‌شات برای هر هفته در 4 هفته گذشته، و --keep-monthly 6 یک اسنپ‌شات برای هر ماه در 6 ماه گذشته را نگه می‌دارد. هر چیزی که توسط این قوانین محافظت نشود، فراموش (forget) می‌شود.

دستور forget به‌تنهایی فقط رکوردهای اسنپ‌شات را حذف می‌کند؛ تکه‌های داده (data chunks) تا زمانی که چیزی آن‌ها را پاک نکند، در مخزن باقی می‌مانند. این دقیقاً همان کاری است که --prune انجام می‌دهد: این دستور تکه‌هایی را که هیچ اسنپ‌شاتی به آن‌ها ارجاع نمی‌دهد پیدا کرده و حذف می‌کند؛ در این مرحله است که فضای دیسک واقعاً آزاد می‌شود. عملیات prune یک کار سنگین روی مخزن است، بنابراین در مخازن بزرگ، برخی افراد forget را به‌صورت شبانه و --prune را به‌صورت هفتگی اجرا می‌کنند؛ اما برای اندازه‌های معمول VPS، اجرای شبانه آن مشکلی ایجاد نمی‌کند.

پایگاه‌های داده: ابتدا dump بگیرید، سپس از dump پشتیبان تهیه کنید

برنامه Restic فایل‌ها را همزمان با خواندن آن‌ها کپی می‌کند، در حالی که پایگاه داده به‌طور مداوم در حال نوشتن در فایل‌های خود است. فایل پایگاه داده‌ای که در حین نوشتن کپی شود، هنگام بازیابی خراب خواهد بود، زیرا کپی حاصل، ترکیبی از صفحات قبل و بعد از عملیات نوشتن است. راه‌حل استاندارد این است: از موتور پایگاه داده بخواهید یک خروجی (export) منسجم در یک فایل ایجاد کند، سپس اجازه دهید restic از آن فایل پشتیبان بگیرد.

برای PostgreSQL، یک خط دستور dump را به ابتدای restic-backup.sh، پیش از دستور restic backup اضافه کنید و دایرکتوری dump را در مسیرهای پشتیبان‌گیری بگنجانید:

mkdir -p /var/backups/db
sudo -u postgres pg_dump myapp | gzip > /var/backups/db/myapp.sql.gz

دستور mysqldump همین نقش را برای MariaDB و MySQL ایفا می‌کند. برای مشاهده یک نمونه عملی از کل این الگو، بخش پشتیبان‌گیری Nextcloud ابتدا حالت maintenance را فعال می‌کند، از Postgres خروجی dump می‌گیرد و فایل‌ها را به عنوان یک مجموعه منسجم کپی می‌کند؛ دقیقاً همان مجموعه‌ای که restic باید هر شب از سرور خارج کند. در مورد SQLite نیز ایده مشابه است اما با ابزاری ساده‌تر: راهنمای Vaultwarden کانتینر را برای چند ثانیه متوقف می‌کند تا یک کپی سرد (cold copy) از db.sqlite3 تهیه کند و همان آرشیو، فایلی است که restic از سرور منتقل می‌کند.

FAQ

آیا پشتیبان‌های restic رمزنگاری‌شده هستند؟

بله، همیشه. هر مخزن restic با AES-256 رمزنگاری می‌شود و هیچ حالت بدون رمزنگاری وجود ندارد. همچنین Restic از رمز عبور خالی خودداری می‌کند مگر اینکه از --insecure-no-password استفاده کنید (موجود از نسخه 0.17.0)، بنابراین مخزنی که طبق این راهنما تنظیم شده، برای هر دستور به رمز عبور نیاز دارد. دستگاه یا ارائه‌دهنده‌ای که مخزن را ذخیره می‌کند، فقط بلاک‌های رمزنگاری‌شده را در اختیار دارد، بنابراین در صورت نفوذ به میزبان پشتیبان، فایل‌های شما فاش نمی‌شوند. معامله قطعی است: بدون رمز عبور، داده‌ها توسط هیچ‌کس قابل بازیابی نیستند، پس یک کپی از آن را دور از سرور نگهداری کنید.

آیا restic پشتیبان‌گیری افزایشی (incremental) انجام می‌دهد؟

هر اسنپ‌شات restic مانند یک پشتیبان کامل عمل می‌کند، در حالی که هزینه ذخیره‌سازی آن افزایشی است. Restic فایل‌ها را به تکه‌هایی تقسیم کرده و فقط تکه‌هایی را آپلود می‌کند که قبلاً در مخزن ذخیره نشده‌اند، بنابراین اجرای شبانه فقط تغییرات آن روز را منتقل می‌کند. برخلاف طرح‌های افزایشی سنتی، هیچ زنجیره‌ای برای بازسازی وجود ندارد: هر اسنپ‌شات مستقیماً بازیابی می‌شود و حذف یک اسنپ‌شات قدیمی، اسنپ‌شات‌های جدیدتر را خراب نمی‌کند.

چگونه فایل‌ها را از پشتیبان restic بازیابی کنم؟

دستور restic snapshots را برای یافتن ID اسنپ‌شات اجرا کنید، سپس از restic restore <id> --target /some/empty/dir برای بازیابی آن استفاده کنید و برای بازیابی بخشی از آن، --include /path را اضافه کنید. latest می‌تواند به‌جای ID استفاده شود. Restic ساختار دایرکتوری اصلی را در مقصد بازسازی می‌کند، بنابراین بازیابی /etc/ssh در /some/empty/dir/etc/ssh قرار می‌گیرد. قبل از اینکه به آن نیاز پیدا کنید، تمرین کنید، زیرا پشتیبان تست‌نشده فقط یک شایعه است.

هر چند وقت یک‌بار باید پشتیبان‌گیری restic را اجرا کنم؟

اجرای شبانه برای یک سرور حداقلِ منطقی است و حذف داده‌های تکراری آن را کم‌هزینه می‌کند: هر اجرا فقط تکه‌هایی را آپلود می‌کند که از آخرین بار تغییر کرده‌اند. داده‌هایی که سریع تغییر می‌کنند یا از دست دادن حتی یک روز از آن‌ها آسیب‌زاست، می‌توانند با همان الگوی زمان‌بندی هر چند ساعت یک‌بار پشتیبان‌گیری شوند. فرکانس، بخش آسان کار است؛ همچنین به‌طور منظم restic check را اجرا کنید و ماهانه تمرین بازیابی داشته باشید، زیرا زمان‌بندی بدون تأیید، آرامش کاذب است.

اگر رمز عبور مخزن restic را گم کنم چه می‌شود؟

پشتیبان‌ها غیرقابل بازیابی هستند. رمزنگاری restic هیچ راه پشتیبان (back door) یا بازنشانی ندارد، بنابراین رمز عبور به اندازه خود پشتیبان‌ها مهم است. یک کپی از آن را در مدیریت رمز عبور خود و هر جای امن دیگری که سرور پشتیبان‌گیری‌شده نیست، نگهداری کنید. تا زمانی که هنوز دسترسی دارید، restic key add می‌تواند رمز عبور دومی را برای همان مخزن ثبت کند که به عنوان پشتیبان عمل می‌کند.