Надійне резервне копіювання системи — це не розкіш, а звичка, яка одного дня заощадить вам багато нервів і часу. У цій інструкції ми налаштуємо інкрементні бекапи за допомогою rsync, оформимо все як зручні bash скрипти і автоматизуємо запуск через systemd timers. Результат: акуратні щоденні копії, мінімальний зайвий трафік і просте відновлення. 🛡️

Чому rsync і як це працює

rsync — легкий, швидкий та універсальний інструмент. Він синхронізує файли локально або по SSH, копіює лише зміни та вміє зберігати права доступу, ACL і extended attributes. Інкрементний підхід із --link-dest дозволяє робити «знімки» каталогів на щоденній основі, використовуючи жорсткі посилання для незмінених файлів. Це економить місце та прискорює резервне копіювання системи.

Підготовка

Перш ніж писати bash скрипти, визначте джерело (наприклад, ваш /home) та ціль (зовнішній диск або NAS). Переконайтеся, що цільовий носій змонтовано, а у вас є права на запис.

# Приклади корисних перевірок
lsblk -f
id -u
mkdir -p /mnt/backup/home

How-to: інкрементні бекапи з Bash-скриптом

Створимо сценарій, який формує датовані «знімки» і посилання latest на актуальний бекап. Це серце нашої автоматизації задач.

Крок 1. Файл виключень для rsync

Щоб не тягнути кеші та великі тимчасові файли, додамо список виключень.

mkdir -p ~/.config/rsync
cat > ~/.config/rsync/exclude.txt <<'EOF'
.cache/
.Trash*/
node_modules/
Downloads/*.iso
*.tmp
*.swap
EOF

Крок 2. Bash-скрипт бекапу

Сценарій робить інкремент, логування та акуратне оновлення посилання на останній бекап.

mkdir -p ~/.local/bin
cat > ~/.local/bin/backup-home.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

SRC="/home/$USER/"
DEST_BASE="/mnt/backup/home"
EXCLUDES="$HOME/.config/rsync/exclude.txt"
DATE="$(date +%F)"
TARGET="$DEST_BASE/$DATE"
LAST="$DEST_BASE/latest"
LOGDIR="$HOME/.local/var/log"
LOGFILE="$LOGDIR/rsync-backup.log"

mkdir -p "$TARGET" "$LOGDIR"

RSYNC_OPTS=(
  -aHAX --delete --numeric-ids --partial --inplace
  --info=stats2,progress2 --human-readable
  --exclude-from="$EXCLUDES"
)

# Підтримка інкрементів через --link-dest
if [[ -d "$LAST" ]]; then
  RSYNC_OPTS+=(--link-dest="$LAST")
fi

# Сухий прогін за бажанням: RSYNC_DRYRUN=1 backup-home.sh
if [[ "${RSYNC_DRYRUN:-0}" == "1" ]]; then
  RSYNC_OPTS+=(-n)
fi

rsync "${RSYNC_OPTS[@]}" "$SRC" "$TARGET" | tee -a "$LOGFILE"

# Оновити симлінк на актуальний бекап
ln -sfn "$TARGET" "$LAST"

# Опціонально: зберігати лише 14 останніх знімків
find "$DEST_BASE" -maxdepth 1 -type d -name '20*' | sort | head -n -14 | xargs -r rm -rf
EOF

chmod +x ~/.local/bin/backup-home.sh

Крок 3. Перевірка в ручному режимі

# Сухий прогін (нічого не копіює)
RSYNC_DRYRUN=1 ~/.local/bin/backup-home.sh

# Реальний запуск
~/.local/bin/backup-home.sh

Автоматизація через systemd timers

systemd timers стабільніші за cron на ноутбуках та десктопах завдяки опції Persistent=true, яка «наздоганяє» пропущені запуски після сну. Це ідеальний варіант для cron та systemd timers сценаріїв.

Крок 4. Створюємо user units

mkdir -p ~/.config/systemd/user

# Сервіс
cat > ~/.config/systemd/user/backup-home.service <<'EOF'
[Unit]
Description=Kernelka rsync backup (home)

[Service]
Type=oneshot
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
ExecStart=%h/.local/bin/backup-home.sh

[Install]
WantedBy=default.target
EOF

# Таймер: щоденно о 02:30 з випадковою затримкою до 10 хв
cat > ~/.config/systemd/user/backup-home.timer <<'EOF'
[Unit]
Description=Daily home backup at 02:30

[Timer]
OnCalendar=*-*-* 02:30
RandomizedDelaySec=10m
Persistent=true
Unit=backup-home.service

[Install]
WantedBy=timers.target
EOF

# Активуємо
systemctl --user daemon-reload
systemctl --user enable --now backup-home.timer

# Перевіряємо розклад
systemctl --user list-timers --all | grep backup-home

Логи та діагностика

journalctl --user -u backup-home.service -e
journalctl --user -u backup-home.timer -e

Альтернативи: cron і віддалені бекапи

Якщо подобається класика, можна використати cron:

crontab -e
# Додайте рядок (щодня о 02:30)
30 2 * * * /home/$USER/.local/bin/backup-home.sh >> /home/$USER/.local/var/log/cron-backup.log 2>&1

Віддалений бекап (через SSH) виглядає так само просто. Замініть DEST_BASE на user@server:/path або створіть окремий скрипт:

rsync -aHAX --delete \
  --exclude-from="$HOME/.config/rsync/exclude.txt" \
  -e "ssh -p 22" /home/$USER/ user@backup-host:/srv/backups/$(hostname)/$(date +%F)/

GUI-спосіб (для швидкого старту)

Якщо хочеться мінімум ручних налаштувань, спробуйте стандартні інструменти середовища: у GNOME — «Backups» (Déjà Dup), для знімків системи — Timeshift. Вони налаштовують графічні політики чи systemd timers самостійно і підійдуть, якщо поки не хочеться занурюватися в тонкощі rsync.

FAQ

Чи безпечно видаляти старі знімки?

Так, кожен знімок — повний каталог. Завдяки --link-dest незмінні файли спільні через жорсткі посилання. Видалення старого знімка не зачепить інші.

Що з правами доступу та розширеними атрибутами?

Прапори -aHAX копіюють права, ACL і xattrs. Для відновлення на іншу систему переконайтеся, що користувачі/групи існують, або використовуйте --numeric-ids.

Скрипт падає при розмонтуванні диска

Додайте перевірку: перед запуском тестуйте, що $DEST_BASE змонтовано, інакше вийдіть із помилкою. Також корисно монтувати диск за UUID у /etc/fstab.

Таймер не спрацьовує після сну

У нас увімкнено Persistent=true. Перевірте статус таймера, годинник системи та що користувацька сесія активна: loginctl list-users. За потреби використовуйте системний таймер у /etc/systemd/system.

Як перевірити бекап?

Порівняйте вибірково каталоги: сухий прогін rsync -n, або порівняння хешів великих файлів. Для критичних даних зробіть пробне відновлення в окрему папку. 🙂

Потрібне шифрування?

Шифруйте цільовий диск через LUKS або використайте інструменти з вбудованим шифруванням (borg, restic). rsync сам не шифрує дані «на спокої», лише канал через SSH.

Порада від Kernelka

Додайте «здоровʼя-перевірку» в скрипт: перевірку наявності вільного місця та сповіщення. Наприклад, надсилайте повідомлення у системний журнал або на пошту при помилці, а також використовуйте --delete обережно — спершу із -n у тестовому запуску. Ніколи не ігноруйте лог-файл: він ваш перший друг при розслідуванні збоїв.

Підсумок

  • Налаштували інкрементне резервне копіювання системи з rsync.
  • Оформили все як зрозумілі bash скрипти з логами та виключеннями.
  • Автоматизували запуск через systemd timers (альтернатива — cron та systemd timers класичного стилю).
  • Передбачили віддалені бекапи та базові перевірки/діагностику.
  • Згадали GUI-варіанти для швидкого старту. 💾