איך מגבים VPS עם Restic בצורה בטוחה
מדריך להגדרת Restic ב-Ubuntu 24.04: יצירת גיבויים מוצפנים ו-deduplicated לאחסון S3 או SFTP, הגדרת טיימר לילי וביצוע שחזור כדי לוודא תקינות.
מדוע גיבוי על אותו השרת אינו נחשב לגיבוי
Restic היא כלי גיבוי חינמי בקוד פתוח. היא שולחת צילומי מצב (snapshots) מוצפנים ובעלי כפילות נמוכה (deduplicated) של הקבצים שלכם למאגר (repository) במקום אחר: VPS שני, מחשב ביתי, או אחסון אובייקטים תואם S3. מדריך זה מסביר כיצד להגדיר אותה ב-Ubuntu 24.04, החל מההתקנה ועד למאגר דרך SFTP, גיבוי ראשון, טיימר systemd לילי, מדיניות שמירה (retention policy), ותרגיל שחזור שמוכיח שהכל עובד. היעד חייב להיות מכשיר אחר, מכיוון שעותק שנמצא על אותו השרת נמחק יחד עם השרת.
ספריית backup/ על המכשיר שאותו היא מגבה מגינה עליכם מפני דבר אחד בלבד: מחיקה בטעות של קובץ. היא לא תשרוד תקלה בדיסק, מכיוון שהיא נמצאה על אותו דיסק. היא לא תשרוד תוקף עם صلاحות root, מכיוון שהם מוחקים את העותקים תחילה. היא לא תשרוד טעות בחשבון שמוחקת את ה-VPS עצמו. המרכז נתונים הכי פחות יעיל בעולם מתבדח על קובץ tar בשם backup_final_v2_REAL שיושב על אותו מערך (array) כמו הנתונים, והבדיחה רלוונטית כי רבים מאיתנו עשו בדיוק את זה. הכלל הוא שהגיבוי חייב להיות מחוץ למכשיר, ו-restic היא הדרך הקלה ביותר לפעול לפיו.
Restic בארבעה מושגים
Repository. המקום שאליו restic כותב. זהו ספרייה בפורמט של restic, המכילה blobs מוצפנים, ורק restic יכול לקרוא אותה. לעולם אין לערוך אותה ידנית; התקשורת איתה מתבצעת באמצעות פקודות restic והכתובת -r.
Snapshot. תמונת מצב של הקבצים שגיביתם בנקודת זמן מסוימת. כל הרצת גיבוי יוצרת snapshot, ניתן לשחזר כל snapshot בנפרד, וכל אחד מהם מתנהג כעותק מלא של הנתונים שלכם באותו רגע.
Deduplication. restic מחלק קבצים לחלקים (chunks) המוגדרים לפי תוכן, ומעלה רק את החלקים שה-repository לא ראה מעולם. הגיבוי הראשון מעלה את כל הנתונים; כל הרצה שאחריו מעלה בערך רק את מה שהשתנה. snapshot יומי של 20 GB שבו השתנו 50 MB יעלה בערך 50 MB, ולכן שמירת עשרות snapshots היא זולה.
Encryption by default. repository של restic תמיד מוצפן (AES-256), וכל פקודה דורשת את סיסמת ה-repository. מארח הגיבוי או ספק האחסון רואים רק blobs מוצפנים. ההשלכה הישירה: אם תאבדו את הסיסמה, הנתונים יימחקו לצמיתות, וזהו תכנון מכוון. שמרו עותק של הסיסמה במקום שאינו השרת הזה. נושא זה חשוב מספיק כדי שיוזכר פעמיים נוספות בהמשך.
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 (long term support) מקפיאה את גרסאות החבילות שלה. זה אינו משפיע על המדריך, שכן גרסה 0.16.4 מבצעת את כל הפעולות המופיעות כאן. אם ברצונכם להשתמש בגרסה החדשה ביותר בשל שיפורי מהירות, הורדו את הקובץ הרץ (single-binary) מהדף של restic project ב-GitHub releases, פרקו אותו באמצעות bunzip2, והתקינו אותו ב-/usr/local/bin/restic; אין צורך בשום פעולה נוספת להתקנת restic.
יצירת ה-repository בשרת אחר באמצעות SFTP
עליכם להכין מכונת יעד: VPS קטן נוסף הוא הפתרון הנפוץ, אך כל מכונה עם שרת SSH ושטח דיסק פנוי תתאים. Restic תומכת ב-SFTP (העברת קבצים דרך SSH), לכן אין צורך להתקין שום דבר בשרת הגיבוי. במדריך זה, שרת הגיבוי הוא 10.0.0.12 עם משתמש בשם restic. אל תשתמשו בשם המשתמש backup: מערכות Ubuntu ו-Debian כוללות חשבון מערכת שמור בשם backup (uid 34, ללא login shell) בכל התקנה, לכן adduser backup ייכשל ו-ssh backup@... יישמר בתוך nologin.
משימת הגיבוי היומית תרוץ כ-root בשרת המגובה, לכן ל-root נדרשת גישת מפתח (key login) לשרת הגיבוי. צרו מפתח ייעודי ללא 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 מסביר את המודל, ההרשאות וכיצד לבטל מפתח בהמשך.
לאחר מכן, סיסמת ה-repository. צרו סיסמה חזקה בתוך קובץ שנגיש רק ל-root:
openssl rand -base64 32 | sudo tee /root/.restic-password
sudo chmod 600 /root/.restic-passwordכעת העתיקו את הסיסמה למנהל הסיסמאות שלכם, לפני שתמשיכו. אם ה-VPS הזה יקרוס, ה-repository יחד עם הסיסמה הזו ישיבו הכל; ה-repository ללא הסיסמה לא ישיב דבר.
אתחול ה-repository:
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יעד חלופי הוא S3-compatible object storage, שהוא הבחירה הנכונה כאשר אין רצון להפעיל מכונה שנייה. כל 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. החרג את ה-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, זמן ונתיבים. ה-IDs הללו הם אלו שמשמשים לשחזור.
הרצות ליליות באמצעות systemd timer
הקלדה של כתובת ה-repository בכל פקודה היא פעולה מייגעת, וגיבוי המופעל ידנית מפסיק להתבצע תוך חודש. ניתן לפתור את שתי הבעיות באמצעות סקריפט אחד ו-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 checksudo chmod 700 /usr/local/bin/restic-backup.shהשורות forget ו-check מוסברות בשני הסעיפים הבאים. כעת לגבי לוח הזמנים: service מסוג oneshot שמריץ את הסקריפט, ו-timer שמפעיל אותו בכל לילה בשעה 03:00. שימוש ב-timer עדיף על פני 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יש להפעיל את ה-timer, ולאחר מכן להריץ את ה-service פעם אחת באופן ידני כדי לוודא שהוא עובד:
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) ש-service יכול לשאת, מופיע ב-running a program as a systemd service on a VPS.
גיבוי הוא רק שמועה עד שמשחזרים אותו
התייחסו למשפט זה כאל מצווה. משימת גיבוי שמסתיימת בהצלחה (green) בכל לילה מוכיחה רק שהמשימה רצה; היא אינה מוכיחה שהנתונים יחזרו אליכם. שתי בדיקות יסגרו את הפער הזה.
ראשית, restic check, שהסקריפט כבר מריץ מדי לילה. הבדיקה מאמתת את מבנה ה-repository ואת ה-index, כך ששיבוש שקט (silent corruption) ב-backup host יתגלה בלילה הבא במקום ביום השחזור. פעם בחודש, הריצו את הגרסה המעמיקה יותר, שמורידה ומאמתת קריפטוגרפית עשירית אקראית מהנתונים בפועל:
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%מכיוון שתת-הקבוצה היא אקראית בכל פעם, הרצות חודשיות עוברות על כל ה-repository מבלי להזדקק להורדה מלאה.
שנית, תרגיל שחזור. תוך שימוש ב-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 לא מדפיס דבר, המשמעות היא שכל byte חזר בדיוק כפי שהיה, וזהו ההוכחה היחידה שקובעת. מחקו את /srv/restore-drill לאחר מכן. בצעו תרגיל זה מדי חודש, ופעם או פעמיים בשנה בצעו את הגרסה המלאה: שחזרו את כל ה-snapshot האחרון על VPS זמני ובדקו שהאפליקציה שלכם אכן עולה ממנו. ביום שבו תזדקקו לכך תחת לחץ, תרצו שזו תהיה פעולה שגרתית שכבר ביצעתם.
Retention: forget plus prune
ללא מדיניות, ה-snapshots נערמים ללא הגבלה וה-repository גדל ללא הפסקה. שורת forget של הסקריפט מחילה מדיניות בכל לילה: --keep-daily 7 שומרת snapshot אחד לכל יום עבור שבעת הימים האחרונים, --keep-weekly 4 אחד לכל שבוע עבור ארבעה שבועות, ו---keep-monthly 6 אחד לכל חודש עבור שישה חודשים. כל מה שאינו מוגן על ידי כלל נמחק.
הפקודה forget לבדה מסירה רק את רשומות ה-snapshot; ה-data chunks נשארים ב-repository עד שמישהו מוחק אותם. זה מה ש---prune מבצע: הוא מוצא chunks ללא הפניות snapshot שנותרו ומוחק אותם, וזה השלב שבו שטח הדיסק משתחרר בפועל. פעולת ה-prune מבצעת עבודה ממשית ב-repository, לכן ב-repository גדול משתמשים לעיתים ב-forget מדי לילה וב---prune פעם בשבוע; בגדלים טיפוסיים של VPS, הרצה מדי לילה מספיקה.
Databases: dump first, then back up the dump
Restic מעתיק קבצים בזמן קריאתם, ומסד נתונים כותב לקבצים שלו באופן רציף. קובץ מסד נתונים פעיל שנתפס באמצע כתיבה ישוחזר כקובץ פגום, מכיוון שהעותק מערבב דפים (pages) שנכתבו לפני ואחרי פעולת הכתיבה. הפתרון הוא סטנדרטי: יש לגרום למנוע מסד הנתונים לייצר ייצוא (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 mode), מבצע dump ל-Postgres, ומעתיק את הקבצים כסט עקבי אחד, בדיוק הסט ש-restic אמור להעביר מחוץ למערכת בכל לילה. SQLite פועל באותה גישה אך בצורה פשוטה יותר: המדריך ל-Vaultwarden עוצר את ה-container לכמה שניות כדי לבצע עותק קר (cold copy) של db.sqlite3, והארכיון הזה הוא מה ש-restic מעביר מהשרת.
FAQ
האם גיבויים של restic מוצפנים?
כן, תמיד. כל restic repository מוצפן באמצעות AES-256. אין מצב ללא הצפנה, וכל פקודה דורשת את סיסמת ה-repository. המכונה או הספק המאחסנים את ה-repository מחזיקים רק blobs מוצפנים, לכן פריצה למארח הגיבוי לא תחשוף את הקבצים שלך. המחיר הוא מוחלט: ללא הסיסמה לא ניתן לשחזר את הנתונים על ידי איש, לכן יש לשמור עותק שלה הרחק מהשרת.
האם restic מבצע גיבויים אינקרמנטליים?
כל snapshot של restic מתנהג כגיבוי מלא, אך צורך נפח אחסון אינקרמנטלי. restic מפצל קבצים ל-chunks ומעלה רק את ה-chunks שה-repository עדיין לא שמר, לכן ריצה nightly מעלה בערך רק את מה שהשתנה באותו יום. בניגוד לשיטות אינקרמנטליות מסורתיות, אין שרשרת שצריך לשחזר: כל 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?
ריצה nightly היא המינימום ההגיוני עבור שרת, ושיטת ה-deduplication הופכת זאת למשתלמת: כל ריצה מעלה רק את ה-chunks שהשתנו מאז הריצה האחרונה. עבור נתונים שמשתנים במהירות, או כאלו שאיבוד של יום אחד מהם יהיה קריטי, ניתן להריץ את הפקודה כל כמה שעות באותו דפוס זמן. התדירות היא החלק הקל; יש להריץ גם restic check באופן קבוע ולבצע תרגיל שחזור פעם בחודש, מכיוון שלו"ז ללא אימות הוא נחמה שקרית.
מה קורה אם איבדתי את הסיסמה ל-restic repository?
הגיבויים לא ניתנים לשחזור. להצפנה של restic אין back door ואין אפשרות לאיפוס, לכן הסיסמה חשובה בדיוק כמו הגיבויים עצמם. שמור עותק ב-password manager שלך ובכל מקום עמיד אחר שאינו השרת שעליו מבוצע הגיבוי. כל עוד יש לך גישה, restic key add יכול לרשום סיסמה שנייה עבור אותו repository, מה שיספק לך גיבוי לסיסמה.