آموزش بکآپ گیری با Restic در Ubuntu 24.04
با Restic فایلهای VPS خود را به صورت رمزگذاری شده و با قابلیت deduplication به یک سرور دیگر یا S3 منتقل کنید. آموزش کامل نصب و تنظیم nightly timer.
چرا بکآپ در همان سرور، بکآپ محسوب نمیشود
Restic یک ابزار بکآپ رایگان و متنباز است که اسنپشاتهای رمزگذاریشده و با قابلیت deduplication را از فایلهای شما به یک مخزن (repository) در جایی دیگر میفرستد: یک VPS دوم، یک سیستم در خانه، یا ذخیرهساز شیئی (object storage) سازگار با S3. این راهنما، راهاندازی آن را در Ubuntu 24.04 پوشش میدهد؛ از نصب گرفته تا ایجاد یک مخزن از طریق SFTP، اولین بکآپ، تنظیم تایمر nightly با systemd، سیاست نگهداری (retention policy) و تمرین بازیابی (restore drill) برای اثبات عملکرد صحیح سیستم. مقصد باید دستگاه دیگری باشد، زیرا کپیای که در همان سرور باقی میماند، با از کار افتادن سرور از بین میرود.
یک دایرکتوری backup/ در همان سیستمی که از آن بکآپ میگیرید، فقط از یک مورد شما را محافظت میکند: حذف تصادفی یک فایل. این بکآپ در صورت خرابی دیسک باقی نمیماند، زیرا روی همان دیسک قرار دارد. در صورت حمله توسط فردی با دسترسی root نیز باقی نمیماند، زیرا آنها ابتدا کپیها را حذف میکنند. همچنین در صورت اشتباه در مدیریت حساب کاربری که منجر به حذف خودِ VPS شود، باقی نمیماند. کمبازدهترین دیتاسنتر جهان درباره یک فایل tarball به نام backup_final_v2_REAL که روی همان آرایهی دادهها قرار دارد، شوخی میکند؛ این شوخی به این دلیل مطرح است که بسیاری از ما دقیقاً همین کار را انجام دادهایم. قانون این است که بکآپ باید خارج از سیستم باشد و restic سادهترین راه برای رعایت این قانون است.
Restic در چهار مفهوم اصلی
Repository. مکانی که restic دادهها را در آن مینویسد. این یک دایرکتوری با فرمت اختصاصی restic است که پر از blobهای رمزگذاری شده است و فقط restic میتواند آن را بخواند. هرگز آن را به صورت دستی ویرایش نکنید؛ شما از طریق دستورات restic و آدرس -r با آن در ارتباط هستید.
Snapshot. تصویری از وضعیت فایلهای بکآپ شده در یک لحظه مشخص. هر اجرای بکآپ یک snapshot ایجاد میکند؛ هر snapshot میتواند به تنهایی بازیابی شود و هر کدام مانند یک کپی کامل از دادههای شما در آن لحظه عمل میکند.
Deduplication. restic فایلها را به تکههایی (chunks) با تعریف محتوا تقسیم میکند و فقط تکههایی را آپلود میکند که repository قبلاً آنها را ندیده است. اولین بکآپ همه چیز را آپلود میکند؛ هر اجرای بعدی تقریباً فقط تغییرات را آپلود میکند. یک snapshot شبانه از 20 GB که در آن 50 MB تغییر کرده است، حدود 50 MB هزینه دارد؛ به همین دلیل نگهداری دهها snapshot کمهزینه است.
Encryption by default. یک repository در restic همیشه رمزگذاری شده است (AES-256) و هر دستوری به رمز عبور repository نیاز دارد. میزبان بکآپ یا ارائهدهنده فضای ذخیرهسازی، فقط blobهای رمزگذاری شده را میبیند. پیامد جدی این موضوع: اگر رمز عبور را گم کنید، دادهها برای همیشه و طبق طراحی سیستم از دست میروند. یک کپی از رمز عبور را در جایی غیر از این سرور نگه دارید. این موضوع آنقدر اهمیت دارد که در ادامه دو بار دیگر به آن اشاره میشود.
Install restic on Ubuntu 24.04
sudo apt update && sudo apt install -y restic
restic versionدر Ubuntu 24.04، نسخه restic 0.16.4 نصب میشود، در حالی که آخرین نسخه رسمی 0.19.1 است. این تفاوت به دلیل ثابت نگه داشتن نسخههای پکیج در نسخههای LTS (پشتیبانی طولانیمدت) است. این موضوع در اینجا اهمیتی ندارد: نسخه 0.16.4 تمام مراحل این راهنما را انجام میدهد. اگر برای بهرهمندی از بهبودهای سرعت، آخرین نسخه را میخواهید، فایل تک-باینری رسمی را از صفحه GitHub releases پروژه restic دانلود کنید، آن را با bunzip2 باز کنید و در /usr/local/bin/restic نصب کنید؛ نصب restic فقط همین است.
ایجاد مخزن (repository) در سرور دیگر از طریق 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 قرار میگیرد.
وظیفه (job) شبانه روی سرور مورد پشتیبانگیری به صورت root اجرا خواهد شد، بنابراین root نیاز به ورود با کلید (key login) به هاست پشتیبان دارد. یک کلید اختصاصی بدون passphrase ایجاد کنید، زیرا هیچ انسانی ساعت 3am برای تایپ آن حضور ندارد، و سپس آن را کپی کنید:
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 key مدل، دسترسیها و نحوه لغو یک کلید را توضیح میدهد.
مرحله بعد، رمز عبور مخزن (repository password) است. یک رمز عبور قوی در فایلی که فقط root به آن دسترسی دارد، ایجاد کنید:
openssl rand -base64 32 | sudo tee /root/.restic-password
sudo chmod 600 /root/.restic-passwordقبل از ادامه مراحل، آن رمز عبور را در مدیریت رمز عبور (password manager) خود کپی کنید. اگر این VPS از کار بیفتد، مخزن به همراه این رمز عبور، همه چیز را بازیابی میکند؛ مخزن بدون رمز عبور هیچ چیز را بازیابی نمیکند.
مقداردهی اولیه (Initialise) مخزن:
sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password initcreated restic repository 9f3c2a1b0d at sftp:restic@10.0.0.12:/srv/restic/web1مقصد جایگزین، ذخیرهسازی اشیاء (object storage) سازگار با S3 است که وقتی نمیخواهید یک ماشین دوم را مدیریت کنید، انتخاب مناسبی است. هر bucket سازگار با S3 به همین صورت عمل میکند؛ تنها آدرس و دو متغیر اعتبارسنجی (credential) تغییر میکنند:
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. از کشها (caches) استثنا کنید، زیرا حجم بالایی دارند، هر روز تغییر میکنند و خودشان دوباره ساخته میشوند:
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 فقط بخشهای (chunks) جدید را آپلود میکند. لیست موارد خود را مشاهده کنید:
sudo restic -r sftp:restic@10.0.0.12:/srv/restic/web1 --password-file /root/.restic-password snapshotsهر snapshot یک ID، یک زمان و مسیرهای موجود در آن را نشان میدهد. آن IDها همان مواردی هستند که از طریق آنها عملیات restore را انجام میدهید.
اجرای شبانه با استفاده از systemd timer
تکرار آدرس مخزن در هر دستور خستهکننده است و بکآپهایی که به صورت دستی اجرا میشوند، معمولاً ظرف مدت یک ماه متوقف میشوند. راه حل هر دو مشکل، استفاده از یک اسکریپت و یک timer است. اسکریپت دو متغیر محیطی RESTIC_REPOSITORY و RESTIC_PASSWORD_FILE را که restic از آنها استفاده میکند، تنظیم میکند تا تمام دستورات داخل اسکریپت کوتاه باقی بمانند:
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 checksudo chmod 700 /usr/local/bin/restic-backup.shخطوط forget و check در دو بخش بعدی توضیح داده شدهاند. در مورد زمانبندی: یک سرویس oneshot که اسکریپت را اجرا میکند، و یک timer که آن را هر شب در ساعت 03:00 اجرا میکند. استفاده از timer نسبت به cron در اینجا برتری دارد، زیرا لاگهای اجرا در journal ذخیره میشوند و Persistent=true بلافاصله پس از بالا آمدن سرور بعد از downtime، بکآپ از دست رفته را اجرا میکند.
# /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.targettimer را فعال کنید، سپس سرویس را یک بار به صورت دستی اجرا کنید تا عملکرد آن را مشاهده کنید:
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 را تولید کنید:
الگوی کامل پشت این دو فایل، شامل سینتکس تقویم و دستورات سختگیرانه (hardening) که یک سرویس میتواند داشته باشد، در running a program as a systemd service on a VPS آمده است.
یک بکآپ تا زمانی که آن را بازیابی نکنید، فقط یک شایعه است
این جمله را به عنوان یک دستورالعمل قطعی در نظر بگیرید. یک Job بکآپ که هر شب با موفقیت (green) اجرا میشود، فقط ثابت میکند که فرآیند اجرا شده است؛ این لزوماً ثابت نمیکند که دادههای شما قابل بازگشت هستند. دو مرحله بررسی، این شک را برطرف میکند.
اول، restic check، که اسکریپت از قبل هر شب آن را اجرا میکند. این مرحله ساختار مخزن (repository) و ایندکس را تأیید میکند تا اگر فساد داده (corruption) در هاست بکآپ رخ داده باشد، به جای روز بازیابی، شب بعد شناسایی شود. ماهی یکبار، نسخه عمیقتر را اجرا کنید که 10 درصد تصادفی از دادههای واقعی را دانلود و از نظر رمزنگاری تأیید میکند:
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%از آنجایی که زیرمجموعه انتخاب شده در هر بار تصادفی است، اجراهای ماهانه بدون نیاز به دانلود کامل، تمام مخزن را پوشش میدهند.
دوم، تمرین بازیابی (restore drill). در حالی که همچنان در root shell مرحله قبل هستید، یک دایرکتوری واقعی از آخرین snapshot را به یک مسیر موقت (scratch location) بازیابی کنید و آن را با فایلهای اصلی مقایسه کنید:
restic restore latest --target /srv/restore-drill --include /etc/ssh
diff -r /etc/ssh /srv/restore-drill/etc/sshاگر خروجی diff خالی بود، به این معناست که تمام بایتها دقیقاً مشابه فایلهای اصلی بازگشتهاند؛ این تنها مدرک معتبر است. پس از اتمام، /srv/restore-drill را حذف کنید. این تمرین را ماهیانه انجام دهید و سالی یک یا دو بار، نسخه کامل را اجرا کنید: کل آخرین snapshot را روی یک VPS موقت بازیابی کنید و بررسی کنید که آیا اپلیکیشن شما واقعاً از روی آن اجرا میشود یا خیر. روزی که در شرایط حساس به این فرآیند نیاز دارید، باید آن را به عنوان یک روال تکرار شده و امتحان شده داشته باشید.
Retention: forget plus prune
بدون یک policy، snapshotها به صورت بیوقفه انباشته میشوند و حجم repository مدام افزایش مییابد. خط forget در این script هر شب یک policy را اعمال میکند: --keep-daily 7 یک snapshot برای هر روز در 7 روز گذشته را نگه میدارد، --keep-weekly 4 یک snapshot برای هر هفته در 4 هفته گذشته، و --keep-monthly 6 یک snapshot برای هر ماه در 6 ماه گذشته. هر آنچه توسط یک rule محافظت نشود، فراموش (forget) میشود.
دستور forget به تنهایی فقط سوابق snapshot را حذف میکند؛ قطعات داده (data chunks) در repository باقی میمانند تا زمانی که چیزی آنها را حذف کند. این دقیقاً همان کاری است که --prune انجام میدهد: این دستور قطعاتی را که هیچ snapshot مرجعی به آنها اشاره نمیکند پیدا کرده و حذف میکند؛ این مرحله است که فضای دیسک واقعاً آزاد میشود. دستور prune عملیات واقعی روی repository را انجام میدهد، بنابراین در repositoryهای بزرگ، برخی افراد forget را به صورت شبانه و --prune را به صورت هفتگی اجرا میکنند؛ در حجمهای معمولی VPS، اجرای شبانه کفایت میکند.
Databases: ابتدا 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.gzmysqldump نقش مشابهی را برای MariaDB و MySQL ایفا میکند. برای مشاهده یک مثال عملی از کل این الگو، بخش بکآپ Nextcloud حالت maintenance را فعال میکند، از Postgres dump میگیرد و فایلها را به عنوان یک مجموعه یکپارچه کپی میکند؛ دقیقاً همان مجموعهای که restic باید هر شب از سیستم خارج کند. در مورد SQLite نیز ایده مشابه است اما با ابزار کوچکتر: راهنمای Vaultwarden کانتینر را برای چند ثانیه متوقف میکند تا یک کپی سرد از db.sqlite3 تهیه کند، و آن آرشیو همان چیزی است که restic از سرور ارسال میکند.
FAQ
آیا بکآپهای restic رمزگذاری شده هستند؟
بله، همیشه. هر repository در restic با AES-256 رمزگذاری میشود؛ هیچ حالت بدون رمزگذاری وجود ندارد و هر دستور به رمز عبور repository نیاز دارد. ماشین یا ارائهدهندهای که repository را ذخیره میکند، فقط شامل blobهای رمزگذاری شده است، بنابراین هک شدن میزبان بکآپ باعث افشای فایلهای شما نمیشود. این یک معامله قطعی است: بدون رمز عبور، هیچکس نمیتواند دادهها را بازیابی کند، بنابراین یک نسخه از آن را دور از سرور نگه دارید.
آیا restic بکآپهای incremental انجام میدهد؟
هر snapshot در restic مانند یک بکآپ کامل عمل میکند، در حالی که هزینه ذخیرهسازی آن incremental است. restic فایلها را به chunkها تقسیم میکند و فقط chunkهایی را آپلود میکند که repository قبلاً ذخیره نکرده است، بنابراین اجرای شبانه فقط حجم تغییرات آن روز را منتقل میکند. برخلاف طرحهای incremental سنتی، هیچ زنجیرهای برای بازپخش (replay) وجود ندارد: هر snapshot مستقیماً بازیابی میشود و حذف یک snapshot قدیمی هرگز باعث خرابی snapshotهای جدیدتر نمیشود.
چگونه فایلها را از یک بکآپ restic بازیابی کنم؟
دستور restic snapshots را برای یافتن snapshot ID اجرا کنید، سپس restic restore <id> --target /some/empty/dir را برای بازیابی آن اجرا کنید و برای بازیابی تنها بخشی از آن، --include /path را اضافه کنید. دستور latest میتواند جایگزین ID استفاده شود. restic ساختار دایرکتوری اصلی را در مقصد بازسازی میکند، بنابراین بازیابی /etc/ssh در مسیر /some/empty/dir/etc/ssh قرار میگیرد. قبل از اینکه به آن نیاز پیدا کنید، این کار را تمرین کنید، زیرا یک بکآپ آزمایشنشده، فقط یک شایعه است.
هر چند وقت یکبار باید restic backup را اجرا کنم؟
اجرای شبانه برای یک سرور، حداقل زمان منطقی است و deduplication هزینه آن را کم میکند: هر اجرا فقط chunkهایی را آپلود میکند که از اجرای قبلی تغییر کردهاند. برای دادههایی که سریع تغییر میکنند، یا از دست دادن حتی یک روز آنها آسیبزا است، میتوان با همان الگوی زمانبندی، هر چند ساعت یکبار اجرا را انجام داد. تعیین فرکانس، بخش آسان کار است؛ همچنین restic check را به طور منظم و یک تمرین بازیابی (restore drill) را به صورت ماهیانه اجرا کنید، زیرا زمانبندی بدون تأیید، آرامش کاذب است.
اگر رمز عبور restic repository خود را گم کنم چه میشود؟
بکآپها غیرقابل بازیابی هستند. رمزگذاری restic هیچ در پشتی (back door) یا قابلیت بازنشانی ندارد، بنابراین رمز عبور به اندازه خودِ بکآپها اهمیت دارد. یک نسخه در مدیریت رمز عبور (password manager) خود و هر جای بادوام دیگری که سرور بکآپ شده نباشد، نگه دارید. تا زمانی که دسترسی دارید، restic key add میتواند رمز عبور دومی را برای همان repository ثبت کند که به شما یک نسخه پشتیبان (spare) میدهد.