CentOSDebianITСофт и ОС

Backup Linux через rsync: SSH-ключ, systemd timer и проверка восстановления

Ниже — рабочая схема резервного копирования каталога Linux на отдельный backup-сервер через rsync и SSH. В примере сохраняются права, ACL, xattrs и hard links, используется отдельный ключ, dry-run, systemd timer и обязательный restore-test.

1. Устанавливаем нужные пакеты

apt update
apt install rsync openssh-client acl attr
rsync --version
ssh -V

2. Создаём отдельный SSH-ключ

install -d -m 700 /root/.ssh
ssh-keygen -t ed25519 -f /root/.ssh/rsync-backup -N '' -C 'server01 rsync backup'
chmod 600 /root/.ssh/rsync-backup
chmod 644 /root/.ssh/rsync-backup.pub

Публичный ключ добавьте пользователю backup на backup-сервере. Проверяем вход:

ssh -i /root/.ssh/rsync-backup backup@backup01 'hostname; id; df -h /backup'

3. Проверяем источник и метаданные

SOURCE=/srv/data
findmnt -T "$SOURCE"
du -sh "$SOURCE"
getfacl -p "$SOURCE" | head -50
getfattr -d -m- "$SOURCE" 2>/dev/null | head -50

4. Первый dry-run

rsync -aHAX --numeric-ids --itemize-changes --dry-run \
  -e 'ssh -i /root/.ssh/rsync-backup -o BatchMode=yes' \
  /srv/data/ backup@backup01:/backup/server01/data/

Обратите внимание на завершающий слэш после /srv/data/: копируется содержимое каталога, а не сам каталог как дополнительный уровень.

5. Выполняем первую копию

rsync -aHAX --numeric-ids --info=stats2,progress2 \
  --partial --partial-dir=.rsync-partial \
  -e 'ssh -i /root/.ssh/rsync-backup -o BatchMode=yes' \
  /srv/data/ backup@backup01:/backup/server01/data/
echo $?

6. Проверяем результат

ssh -i /root/.ssh/rsync-backup backup@backup01 \
  'du -sh /backup/server01/data; find /backup/server01/data -type f | wc -l'

rsync -aHAX --numeric-ids --checksum --dry-run --itemize-changes \
  -e 'ssh -i /root/.ssh/rsync-backup -o BatchMode=yes' \
  /srv/data/ backup@backup01:/backup/server01/data/

Пустой итоговый список изменений при checksum-проверке означает, что содержимое совпадает. На больших объёмах --checksum создаёт нагрузку, поэтому не запускайте его слишком часто.

7. Создаём backup-скрипт

cat > /usr/local/sbin/rsync-backup.sh <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

SRC=/srv/data/
DST=backup@backup01:/backup/server01/data/
KEY=/root/.ssh/rsync-backup
STAMP=/var/lib/rsync-backup/last-success

install -d -m 700 /var/lib/rsync-backup

rsync -aHAX --numeric-ids \
  --partial --partial-dir=.rsync-partial \
  --timeout=120 \
  -e "ssh -i $KEY -o BatchMode=yes -o ConnectTimeout=15" \
  "$SRC" "$DST"

touch "$STAMP"
EOF
chmod 700 /usr/local/sbin/rsync-backup.sh
/usr/local/sbin/rsync-backup.sh

8. Добавляем systemd service и timer

cat > /etc/systemd/system/rsync-backup.service <<'EOF'
[Unit]
Description=Rsync backup to backup01
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/rsync-backup.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
EOF

cat > /etc/systemd/system/rsync-backup.timer <<'EOF'
[Unit]
Description=Daily rsync backup

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

[Install]
WantedBy=timers.target
EOF

systemctl daemon-reload
systemctl enable --now rsync-backup.timer
systemctl start rsync-backup.service
systemctl status rsync-backup.service --no-pager
systemctl list-timers rsync-backup.timer

9. Контролируем последний успешный запуск

stat /var/lib/rsync-backup/last-success
journalctl -u rsync-backup.service -n 100 --no-pager
df -h
df -i

10. Осторожно с —delete

Перед включением зеркальной очистки обязательно выполните:

rsync -aHAX --numeric-ids --delete --dry-run --itemize-changes \
  -e 'ssh -i /root/.ssh/rsync-backup -o BatchMode=yes' \
  /srv/data/ backup@backup01:/backup/server01/data/

--delete допустим только при наличии snapshots или отдельной истории версий на backup-сервере. Иначе случайное удаление сразу уничтожит и копию.

11. Restore-test

install -d -m 700 /root/restore-test
rsync -aHAX --numeric-ids \
  -e 'ssh -i /root/.ssh/rsync-backup -o BatchMode=yes' \
  backup@backup01:/backup/server01/data/testdir/ /root/restore-test/testdir/

find /root/restore-test/testdir -type f -printf '%m %u:%g %p\n' | head
getfacl -p /root/restore-test/testdir | head -50
getfattr -d -m- /root/restore-test/testdir 2>/dev/null | head -50

Для содержимого сравните checksum:

diff -u \
  <(cd /srv/data/testdir && find . -type f -print0 | sort -z | xargs -0 sha256sum) \
  <(cd /root/restore-test/testdir && find . -type f -print0 | sort -z | xargs -0 sha256sum)

12. Rollback

systemctl disable --now rsync-backup.timer
rm -f /etc/systemd/system/rsync-backup.timer /etc/systemd/system/rsync-backup.service
systemctl daemon-reload
rm -f /usr/local/sbin/rsync-backup.sh

Критерий успеха: ручной и systemd-запуск возвращают код 0, timestamp последнего успеха обновляется, повторный dry-run не показывает неожиданных изменений, restore-test возвращает файлы с совпадающими checksum, ACL и xattrs.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *