Резервное копирование с rsync
rsync копирует каталоги быстро и экономно, передавая только изменившиеся данные, — локально на другой диск или на удалённый сервер по SSH. В этой статье: ключевые флаги -a, -v, -z, --delete, бэкап каталога на другой сервер mHost и скрипт-обёртка, которую можно поставить на расписание через cron.
Что понадобится
- VPS mHost на Ubuntu 22.04/24.04, Debian 11/12 или AlmaLinux/Rocky Linux 8/9 — сервер-источник, который нужно бэкапить.
- Второй сервер (например, ещё один VPS mHost) или отдельный диск/раздел на этом же сервере — куда складывать копии.
- Доступ по SSH под
rootлибо пользователем с правамиsudo: к серверу-источнику, а для удалённого варианта — и к серверу назначения. - Пакет
rsync— обычно уже есть в системе, но стоит проверить (шаг 1).
Ключевые флаги: -a, -v, -z, --delete
Флаг -a (--archive) — самый важный: это сокращение для -rlptgoD. rsync рекурсивно обходит каталоги (-r), сохраняет символические ссылки как ссылки (-l), права доступа (-p), время модификации (-t), группу (-g) и владельца (-o), а также файлы устройств и спецфайлы (-D). При этом -a не сохраняет ACL (-A), расширенные атрибуты (-X), время последнего доступа (-U), время создания (-N) и жёсткие ссылки (-H) — при необходимости их нужно добавлять отдельно.
-v(--verbose) — выводит список передаваемых файлов и краткую сводку в конце. Для большей детализации используйте-vv.-z(--compress) — сжимает данные на лету перед передачей по сети. Заметно помогает на медленных или ограниченных по трафику каналах; на быстрой сети между серверами в одном дата-центре выигрыш обычно небольшой, а для уже сжатых файлов (архивы, видео, изображения) — почти нулевой.--delete— удаляет на приёмнике файлы, которых уже нет в источнике, чтобы копия оставалась точным зеркалом, а не просто накапливала файлы годами.
Шаг 1. Убедитесь, что rsync установлен
rsync нужен на обеих сторонах — и на сервере-источнике, и на сервере, куда складываются копии.
Проверьте, установлен ли он:
rsync --versionЕсли команда не найдена — установите пакет.
Ubuntu / Debian:
sudo apt update
sudo apt install -y rsyncAlmaLinux / Rocky Linux:
sudo dnf install -y rsyncПовторите проверку (и, если нужно, установку) на обоих серверах.
Шаг 2. Настройте вход по SSH-ключу на сервер назначения
Скрипт-обёртка (шаг 5) и cron (шаг 6) будут запускать rsync без вашего участия — вход по паролю здесь не подойдёт, нужна аутентификация по SSH-ключу без passphrase. Выполните команды ниже на сервере-источнике, под тем пользователем, от имени которого будет работать бэкап (обычно root).
- Сгенерируйте отдельный ключ для бэкапов:
ssh-keygen -t ed25519 -f /root/.ssh/id_rsync_backup -N ""-N "" — пустая passphrase: без неё скрипт, запущенный из cron, не сможет ввести пароль от ключа.
- Скопируйте публичный ключ на сервер назначения —
backupв примере ниже может быть любым существующим на сервере назначения пользователем (в том числеroot), у которого есть доступ на запись в целевой каталог:
ssh-copy-id -i /root/.ssh/id_rsync_backup.pub backup@203.0.113.10При первом запуске ssh-copy-id спросит пароль (или воспользуется вашим текущим ключом) для входа на backup@203.0.113.10 — это нормально, дальше новый ключ будет пускать без пароля.
Замените backup@203.0.113.10 на пользователя и адрес вашего сервера назначения.
- Проверьте, что подключение проходит без пароля:
ssh -i /root/.ssh/id_rsync_backup backup@203.0.113.10 "echo OK"Если в ответ пришло OK без запроса пароля — можно переходить к самому rsync.
Шаг 3. Локальная синхронизация каталога
Локальный вариант полезен, если нужно зеркалировать каталог на другой диск, раздел или примонтированное сетевое хранилище на этом же сервере — без SSH и второго сервера.
Сначала — пробный прогон с -n (--dry-run), ничего не меняющий на диске:
rsync -avzn --delete /var/www/ /mnt/backup/www/Проверьте вывод и, если всё выглядит верно, запустите по-настоящему (без -n):
rsync -avz --delete /var/www/ /mnt/backup/www/Шаг 4. Бэкап каталога на другой сервер по SSH
Отличие от локального варианта — приёмник указывается как пользователь@хост:путь, через двоеточие. Сначала — тот же пробный прогон:
rsync -avzn --delete -e "ssh -i /root/.ssh/id_rsync_backup" /var/www/ backup@203.0.113.10:/backup/myserver/www/Проверьте вывод и запустите по-настоящему:
rsync -avz --delete -e "ssh -i /root/.ssh/id_rsync_backup" /var/www/ backup@203.0.113.10:/backup/myserver/www/Что добавилось по сравнению с локальным вариантом:
backup@203.0.113.10:/backup/myserver/www/— пользователь, IP (или домен) сервера назначения и путь на нём.-e "ssh -i /root/.ssh/id_rsync_backup"— явно указывает rsync использовать SSH с конкретным файлом ключа из шага 2. Если бы ключ лежал под стандартным именем (~/.ssh/id_ed25519илиid_rsa) на стандартном 22-м порту,-eможно было бы вообще не указывать — современный rsync и так использует SSH по умолчанию.-eнужен, когда SSH требуются нестандартные параметры: свой файл ключа или нестандартный порт (-e "ssh -p 2222 -i /root/.ssh/id_rsync_backup").
Как и в локальном варианте, заранее создайте каталог на сервере назначения:
ssh -i /root/.ssh/id_rsync_backup backup@203.0.113.10 "mkdir -p /backup/myserver/www"Шаг 5. Скрипт-обёртка для регулярных бэкапов
Чтобы не набирать команду вручную, оформите её в скрипт: с логом, обработкой ошибок и защитой от повторного запуска, если предыдущий бэкап ещё не завершился.
Создайте файл:
sudo nano /usr/local/sbin/rsync-backup.shСодержимое:
#!/usr/bin/env bash
set -euo pipefail
# Source directory and backup destination
SRC="/var/www/"
DEST_USER="backup"
DEST_HOST="203.0.113.10"
DEST_PATH="/backup/myserver/www/"
SSH_KEY="/root/.ssh/id_rsync_backup"
LOG_FILE="/var/log/rsync-backup.log"
LOCK_FILE="/var/lock/rsync-backup.lock"
# Prevent overlapping runs if the previous backup is still going
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
echo "$(date '+%Y-%m-%d %H:%M:%S') Previous backup is still running, exiting" >> "$LOG_FILE"
exit 1
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') Backup started" >> "$LOG_FILE"
if rsync -avz --delete -e "ssh -i ${SSH_KEY}" "$SRC" "${DEST_USER}@${DEST_HOST}:${DEST_PATH}" >> "$LOG_FILE" 2>&1; then
echo "$(date '+%Y-%m-%d %H:%M:%S') Backup finished OK" >> "$LOG_FILE"
else
echo "$(date '+%Y-%m-%d %H:%M:%S') Backup FAILED" >> "$LOG_FILE"
exit 1
fiСделайте скрипт исполняемым и доступным только root:
sudo chmod 700 /usr/local/sbin/rsync-backup.shЗапустите вручную и проверьте лог:
sudo /usr/local/sbin/rsync-backup.sh
tail -n 20 /var/log/rsync-backup.logШаг 6. Поставьте скрипт на расписание в cron
Откройте crontab пользователя root (того же, под кем настроен SSH-ключ в шаге 2):
sudo crontab -eДобавьте строку — например, ежедневный запуск в 02:30:
30 2 * * * /usr/local/sbin/rsync-backup.shСкрипт сам ведёт лог в /var/log/rsync-backup.log, поэтому дополнительно перенаправлять вывод в crontab не обязательно.
Подробный разбор синтаксиса cron, других вариантов расписания (по часам, по дням недели) и типичных ошибок — в статье «Автоматизация бэкапов через cron».
Что дальше
rsync с --delete хранит только последнее состояние каталога, а не версии и историю: если файл случайно испортился давно, старой копии уже не будет — её удалит тот же --delete. Для версионных и зашифрованных бэкапов с дедупликацией посмотрите статью про restic: «Резервное копирование с restic».