Инкрементальные бэкапы с restic
restic — консольная программа для резервного копирования, которая шифрует данные ещё на стороне клиента, хранит их дедуплицированно и после первого полного снимка загружает только изменения. В этой статье вы установите restic на VPS mHost, создадите репозиторий (на локальном диске, на другом сервере по SFTP или в S3), сделаете и восстановите бэкап, а также настроите политику хранения, чтобы старые снимки не копились бесконечно.
Что понадобится
- VPS mHost на Ubuntu 22.04/24.04, Debian 11/12 или AlmaLinux/Rocky Linux 8/9.
- Доступ по SSH под
rootили пользователем сsudo. - Куда складывать бэкапы — один из вариантов шага 3: смонтированный отдельный диск на этом же сервере, второй сервер (например, ещё один VPS mHost) с доступом по SSH, либо bucket в S3 или S3-совместимом хранилище с ключами доступа.
- Данные, которые нужно защитить, — в примерах ниже это
/etcи/var/www; замените на свои пути.
Как это устроено: шифрование, дедупликация, инкрементальность
- Шифрование. restic шифрует данные ещё на клиенте, до отправки в репозиторий, — AES-256 в режиме счётчика (CTR) плюс Poly1305-AES в качестве MAC для проверки целостности. Даже если репозиторий лежит на чужом сервере или в публичном облаке, без пароля прочитать его содержимое не получится.
- Дедупликация. Файлы режутся на фрагменты переменного размера (content-defined chunking, по отпечаткам Rabin) — обычно от 512 КиБ до 8 МиБ, в среднем около 1 МиБ; файлы меньше 512 КиБ не режутся вовсе. Каждый фрагмент адресуется по хешу SHA-256, и одинаковые фрагменты — даже из разных файлов и разных снимков — физически хранятся в репозитории только один раз.
- Инкрементальность. При каждом новом
restic backuprestic читает файлы заново, но благодаря дедупликации загружает в репозиторий только те фрагменты, которых там ещё нет, — фактически только изменения. При этом каждый снимок (snapshot) в списке выглядит как полноценный самостоятельный бэкап: чтобы восстановиться, не нужно искать «полный» бэкап и вручную накатывать на него цепочку инкрементов, как в классических схемах full+incremental, — берёте любой снимок и восстанавливаетесь прямо из него.
Шаг 1. Установите restic
Готового рецепта VMmanager 6 для restic нет (в отличие, например, от Zabbix или LEMP — полный список того, что ставится в один клик, в статье «Готовые рецепты VMmanager 6») — ставится restic одной командой из штатных репозиториев.
Ubuntu / Debian
apt update
apt install -y resticAlmaLinux / Rocky Linux
Пакет restic не входит в базовые репозитории — подключите EPEL:
dnf install -y epel-release
dnf install -y resticПроверьте версию:
restic versionШаг 2. Задайте пароль репозитория
Пароль репозитория — это то, из чего restic выводит ключ шифрования. Сам restic пароль нигде в открытом виде не хранит и восстановить его не может — только вы.
Сгенерируйте случайный пароль и сохраните его в файл, доступный на чтение только root:
mkdir -p /etc/restic
openssl rand -base64 48 > /etc/restic/password.txt
chmod 600 /etc/restic/password.txtПароль можно передавать restic тремя способами:
RESTIC_PASSWORD— сам пароль прямо в переменной окружения (виден в выводеpsи истории команд — для сервера не лучший вариант);RESTIC_PASSWORD_FILE(или флаг--password-file) — путь к файлу с паролем, как созданный выше;RESTIC_PASSWORD_COMMAND(или флаг--password-command) — команда, которая выводит пароль в stdout, например обращение к менеджеру паролей.
Экспортируйте переменную на файл — дальше по статье restic будет брать пароль из него и не станет спрашивать интерактивно:
export RESTIC_PASSWORD_FILE=/etc/restic/password.txtШаг 3. Создайте репозиторий (restic init)
Репозиторий — это то место, куда restic пишет зашифрованные и дедуплицированные данные. restic поддерживает и другие бэкенды (Backblaze B2, Azure Blob Storage, Google Cloud Storage, rclone, REST-сервер и другие) — здесь разберём три варианта, которые чаще всего нужны на VPS. Выберите один.
Локальный диск
Подходит для отдельного смонтированного диска на этом же сервере — например, для быстрого локального восстановления. Как единственная защита не годится: при потере или аварии самого сервера пропадёт и репозиторий вместе с ним — для надёжной защиты нужна ещё и копия за пределами этого сервера (SFTP или S3, см. варианты ниже).
mkdir -p /mnt/backup/restic-repo
export RESTIC_REPOSITORY=/mnt/backup/restic-repo
restic initПо SFTP на другой сервер
Понадобится второй сервер (например, ещё один VPS mHost в другой локации) с SSH и беспарольным входом по ключу — без этого автоматический бэкап по расписанию будет останавливаться на запросе пароля. Пользователь resticbackup ниже — обычный пользователь на сервере-приёмнике (подойдёт и root, но отдельный пользователь безопаснее); создайте его заранее, если такого ещё нет.
Сгенерируйте отдельный ключ и скопируйте его на сервер-приёмник:
ssh-keygen -t ed25519 -f ~/.ssh/restic_backup -N ""
ssh-copy-id -i ~/.ssh/restic_backup.pub resticbackup@backup.example.comДобавьте настройки для этого хоста в ~/.ssh/config — restic использует обычный SSH, поэтому подхватит их сам:
cat >> ~/.ssh/config <<'EOF'
Host backup.example.com
IdentityFile ~/.ssh/restic_backup
ServerAliveInterval 60
ServerAliveCountMax 240
EOFСоздайте репозиторий:
export RESTIC_REPOSITORY="sftp:resticbackup@backup.example.com:/srv/restic-repo"
restic initВ S3 или S3-совместимом хранилище
Подойдёт Amazon S3 или любое S3-совместимое object storage — синтаксис отличается только URL.
Задайте ключи доступа:
export AWS_ACCESS_KEY_ID=<MY_ACCESS_KEY>
export AWS_SECRET_ACCESS_KEY=<MY_SECRET_ACCESS_KEY>Amazon S3:
export RESTIC_REPOSITORY="s3:s3.us-east-1.amazonaws.com/mhost-backups"
restic initДругое S3-совместимое хранилище — вместо адреса AWS укажите endpoint провайдера:
export RESTIC_REPOSITORY="s3:https://s3.example-provider.com/mhost-backups"
restic initПосле того как репозиторий создан, сохраните обе переменные в файл — он понадобится в новых SSH-сессиях и в шаге 8 для cron:
cat > /etc/restic/env <<'EOF'
export RESTIC_REPOSITORY="sftp:resticbackup@backup.example.com:/srv/restic-repo"
export RESTIC_PASSWORD_FILE=/etc/restic/password.txt
EOF
chmod 600 /etc/restic/envШаг 4. Сделайте первый бэкап (backup)
Список исключений — файлы и папки, которые бэкапить не нужно (логи, временные файлы и подобное). Создайте /etc/restic/excludes.txt:
cat > /etc/restic/excludes.txt <<'EOF'
*.log
*/node_modules
*/.git
EOFЗапустите первый бэкап — например, конфигурации сервера и файлов сайта:
restic backup --tag daily --exclude-file=/etc/restic/excludes.txt /etc /var/wwwrestic обойдёт указанные пути, зашифрует данные и загрузит их в репозиторий, а в конце покажет сводку: сколько файлов новых/изменённых/без изменений, сколько данных добавлено в репозиторий (Added to the repository: ...) и ID нового снимка.
Запустите ту же команду ещё раз, не меняя файлы:
restic backup --tag daily --exclude-file=/etc/restic/excludes.txt /etc /var/wwwВо второй раз restic всё равно читает все файлы заново — иначе не понять, что изменилось, — но благодаря дедупликации почти нечего загружать: в сводке будет Added to the repository: 0 B (0 B stored). Это и есть инкрементальность на практике.
Шаг 5. Посмотрите список снимков (snapshots)
restic snapshotsКоманда выведет таблицу по всем снимкам в репозитории: короткий ID снимка, дата и время создания, хост, теги (если задавали --tag) и список путей, которые вошли в снимок. ID снимка (первых нескольких символов достаточно, если они уникальны в репозитории) понадобится в следующем шаге для восстановления конкретной версии.
Шаг 6. Восстановите данные (restore)
Восстановить можно последний снимок:
restic restore latest --target /tmp/restoreИли конкретный — по ID из restic snapshots:
restic snapshots
restic restore 79766175 --target /tmp/restorerestic не перезаписывает файлы на месте — он воссоздаёт полный исходный путь внутри --target. Например, если бэкапили /etc, после восстановления с --target /tmp/restore конфиги окажутся в /tmp/restore/etc/.... Сравните восстановленные файлы с текущими и скопируйте нужное в боевое расположение вручную — так вы не затрёте случайно рабочую конфигурацию неудачным восстановлением.
Восстановить только часть снимка — например, один каталог — можно флагом --include:
restic restore latest --target /tmp/restore --include /etc/nginxШаг 7. Ретеншн-политика: forget --prune
Без политики хранения каждый бэкап добавляет новый снимок, и список снимков растёт бесконечно. Команда forget убирает старые снимки по заданным правилам, но физически освобождает место, занятое больше не нужными данными, только prune — отдельной командой либо сразу, если добавить к forget флаг --prune.
Сначала проверьте, что политика удалит именно то, что вы ожидаете, — с --dry-run ничего не удаляется по-настоящему:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --dry-runЕсли результат ожидаемый, выполните по-настоящему — сразу с --prune, чтобы освободить место, занятое удалёнными снимками:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune--keep-daily 7— хранить по одному снимку за последние 7 дней, в которые был бэкап;--keep-weekly 4— плюс по одному снимку за 4 предыдущие недели;--keep-monthly 6— плюс по одному снимку за 6 предыдущих месяцев.
Снимок сохраняется, если подходит хотя бы под одно из условий (условия работают через «ИЛИ», а не все одновременно). Есть и более простой вариант — --keep-last N, оставить только N последних снимков независимо от календаря. По умолчанию restic группирует снимки по хосту и набору путей и применяет политику к каждой группе отдельно — это важно, если один и тот же репозиторий используют несколько серверов или в нём бэкапятся разные наборы путей.
Шаг 8. Автоматизируйте через cron
Заверните бэкап и очистку старых снимков в один скрипт:
cat > /usr/local/bin/restic-backup.sh <<'EOF'
#!/bin/bash
set -euo pipefail
source /etc/restic/env
restic backup --tag daily --exclude-file=/etc/restic/excludes.txt /etc /var/www
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
EOF
chmod +x /usr/local/bin/restic-backup.shПроверьте его вручную перед тем, как доверить cron:
/usr/local/bin/restic-backup.shДобавьте задание в crontab — например, каждую ночь в 03:00:
crontab -e0 3 * * * /usr/local/bin/restic-backup.sh >> /var/log/restic-backup.log 2>&1Что дальше
Полный разбор автоматизации через cron — в статье «Бэкапы по расписанию: cron». Если для ваших задач достаточно простого зеркалирования файлов на другой сервер без шифрования и дедупликации — см. «Бэкапы через rsync».