restic - лучший универсальный инструмент для бэкапа сервера в хранилище S3. Каждый запуск загружает только те фрагменты, которые изменились с прошлого раза, всё шифруется до того, как покинет машину, каждый запуск - это снимок, который можно восстановить сам по себе, а срок хранения задаётся одной командой - restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune. Настройка - это четыре переменные окружения и restic init. Обдумать нужно пароль, который никто не сможет для вас восстановить, способ, которым вы передаёте ему дампы баз данных, и привычку время от времени что-нибудь восстанавливать, чтобы доказать, что вся цепочка работает. Всё это разобрано в статье на примере любого S3-совместимого эндпоинта.
Как restic хранит бэкап#
Понимание формата репозитория объясняет поведение restic: почему второй бэкап быстрый, почему forget не освобождает места и почему пароль так важен.
- Фрагменты (chunks). restic разбивает файлы на фрагменты переменного размера с помощью разбиения по содержимому, поэтому вставка байт в середину файла меняет только фрагменты вокруг места вставки. Каждый фрагмент идентифицируется своим хешем SHA-256.
- Дедупликация. Фрагмент, который уже есть в репозитории, никогда не загружается повторно - ни из того же файла, ни из другого файла, ни из другого снимка, ни с другой машины, делающей бэкап в тот же репозиторий.
- Pack-файлы. Фрагменты упаковываются в pack-файлы - это те объекты, которые вы видите в бакете под
data/. Индексы вindex/записывают, какой фрагмент в каком pack-файле лежит. - Снимки (snapshots). Снимок в
snapshots/- небольшая запись, указывающая на дерево каталогов и файлов, которые указывают на фрагменты. Каждый снимок - полный бэкап, который можно восстановить, хотя почти все данные у него общие с соседними снимками. - Шифрование. Всё - данные, имена файлов, индексы, снимки - шифруется AES-256 и аутентифицируется Poly1305 перед загрузкой. Провайдер хранилища видит непрозрачные объекты.
- Сжатие. Формат репозитория версии 2, используемый по умолчанию начиная с restic 0.14, сжимает данные zstd перед шифрованием.
Мастер-ключ репозитория зашифрован вашим паролем. Восстановления не существует. Потеряете пароль - и репозиторий станет нечитаемым, и для вас, и для кого угодно ещё. В этом и смысл такого устройства, и поэтому первый раздел ниже посвящён тому, где хранится пароль.
Настройка репозитория#
Установите restic из дистрибутива, если там свежая версия, или скачайте бинарный файл из релизов проекта на GitHub; для всего в этой статье restic version должен показывать 0.17 или новее, а restic self-update обновляет официальный бинарный файл на месте.
Держите настройки в файле, который может читать только root:
export AWS_ACCESS_KEY_ID=RNAKEXAMPLE123export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYexport AWS_DEFAULT_REGION=us-east-1export RESTIC_REPOSITORY=s3:https://s3.example.com/my-bucket/restic/web-01export RESTIC_PASSWORD_FILE=/root/.restic-password$ chmod 600 /root/.restic-env /root/.restic-password$ . /root/.restic-env$ restic -o s3.bucket-lookup=path initcreated restic repository 2f1c9e7a8b at s3:https://s3.example.com/my-bucket/restic/web-01Составные части:
- `RESTIC_REPOSITORY` - это
s3:, за которым следуют URL эндпоинта, бакет и необязательный префикс. Префикс для каждой машины (restic/web-01) разделяет репозитории в одном бакете. Для эндпоинта на обычном HTTP пишитеs3:http://host:port/bucket/prefix. - `-o s3.bucket-lookup=path` принудительно включает path-style адресацию. Умолчание restic,
auto, уже использует path-style для эндпоинтов, которые не принадлежат Amazon или Google, но явное указание ничего не стоит и переживёт будущую смену умолчания. - Регион берётся из
AWS_DEFAULT_REGIONили-o s3.region=us-east-1. С эндпоинтом, который принимает любой регион, подойдёт любое имя, но оно должно быть одинаковым. - `RESTIC_PASSWORD_FILE` указывает на файл с паролем репозитория. Сгенерируйте длинный случайный (
openssl rand -base64 32) и сохраните копию в менеджере паролей прямо сейчас, до первого бэкапа, а не после.
В RE:NODE access key и secret key генерируются для сервера хранилища и показываются в панели, а первый бакет, куда можно положить репозиторий, уже существует. Эндпоинт - это адрес и порт тарифа по обычному HTTP или ваше имя хоста по HTTPS через слот прокси тарифа, который выпускает и продлевает сертификат. restic в любом случае шифрует всё перед загрузкой, но HTTPS скрывает ещё и ваш access key ID и метаданные запросов, так что предпочитайте его.
Бэкап файлов#
$ restic backup /srv/minecraft /etc \ --exclude-file /root/restic-excludes.txt \ --exclude-caches --one-file-system \ --tag nightly/srv/minecraft/logs/srv/minecraft/cache*.tmp**/node_modulesОпции в этой команде:
--exclude-fileчитает шаблоны по одному на строку;--excludeпринимает один в командной строке. Варианты--iexcludeне учитывают регистр.--exclude-cachesпропускает каталоги, содержащие стандартный файлCACHEDIR.TAG.--exclude-if-present .nobackupпропускает каталоги с файлом-маркером, который вы создаёте сами.--one-file-systemостаётся в пределах файловых систем указанных путей, чтобы не затянуть смонтированный сетевой ресурс или/proc.--tagпомечает снимок; по тегам можно выбирать снимки вforgetиrestore.
Первый запуск загружает всё. Последующие читают метаданные каждого файла, перечитывают файлы, у которых изменились размер или время изменения, и загружают только новые фрагменты - сервер на 30 GB с несколькими сотнями мегабайт изменений в день обычно укладывается в минуты. Итоговая строка в конце показывает, сколько добавлено; это число стоит записывать в журнал, потому что ночной бэкап, который вдруг ничего не добавляет или добавляет в десять раз больше обычного, - ваше самое раннее предупреждение о том, что что-то изменилось.
Делайте бэкап согласованных данных. Игровой сервер, записывающий мир во время бэкапа, даёт снимок наполовину записанного мира. Остановите сервер или сначала сбросьте данные на диск и приостановите сохранение, как объясняется в статье бэкапы сервера, которые реально восстанавливаются; для игровых серверов команды сохранения для каждой игры разобраны в статье бэкапы игровых серверов в S3.
Бэкап баз данных#
Никогда не делайте бэкап каталога данных работающей базы данных файловым инструментом. Делайте бэкап дампа. restic может сохранить дамп без временного файла, читая его из команды:
$ restic backup --stdin-from-command --stdin-filename app.sql --tag mysql \ -- mysqldump --single-transaction --routines --triggers app--stdin-from-command (restic 0.17 и новее) запускает команду и сохраняет её вывод в снимке как файл app.sql. Главное: если mysqldump завершится с ошибкой, restic снимок не создаст. Старая форма, mysqldump app | restic backup --stdin --stdin-filename app.sql, не видит код выхода дампа: дамп, упавший на полпути, сохраняется как успешный обрезанный бэкап. Если вы застряли на старом restic, используйте set -o pipefail в bash и проверяйте код выхода сами.
Не сжимайте дамп, прежде чем отдать его restic. Несжатые дампы хорошо дедуплицируются - большинство вчерашних строк сегодня всё ещё на месте, - а restic сжимает данные сам. Сжатый gzip дамп от одного дня к другому меняется почти целиком и сводит дедупликацию на нет.
Та же схема работает для pg_dump, mongodump --archive и им подобных. Учётные данные для дампа должны лежать в файле параметров клиента, например ~/.my.cnf для MySQL, а не в командной строке, где их покажет ps. Каждый движок разобран в статье дампы баз данных в S3 по расписанию, а флаги дампа - в статье бэкап и восстановление через mysqldump.
Снимки, срок хранения, forget и prune#
$ restic snapshotsID Time Host Tags Paths----------------------------------------------------------------4f2a1c9e 2026-10-06 04:30:12 web-01 nightly /etc, /srv/minecrafta81d0b37 2026-10-07 04:30:09 web-01 nightly /etc, /srv/minecraftc5e9f210 2026-10-08 04:30:11 web-01 nightly /etc, /srv/minecraftСрок хранения - это два шага. forget удаляет записи снимков по политике; prune удаляет данные, на которые не ссылается ни один оставшийся снимок. Пока вы не выполните prune, место не освобождается.
| Флаг | Сохраняет |
|---|---|
--keep-last n | n самых свежих снимков |
--keep-hourly n | Последний снимок каждого из n последних часов, в которые были снимки |
--keep-daily n | По одному в день за n дней, в которые были снимки |
--keep-weekly n | По одному в неделю |
--keep-monthly n | По одному в месяц |
--keep-yearly n | По одному в год |
--keep-within 30d | Всё, что новее указанного срока |
--keep-tag name | Каждый снимок с этим тегом |
Политики сочетаются - снимок сохраняется, если его сохраняет хоть одно правило, - и применяются отдельно к каждой группе снимков с одинаковыми хостом и путями (--group-by host,paths - умолчание), так что снимки базы данных и снимки файлов хранят каждый свою историю.
$ restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --dry-run$ restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --pruneВ первый раз обязательно прочитайте вывод --dry-run. --keep-tag locked - полезное дополнение: пометьте заведомо рабочий снимок тегом locked, и никакая политика его не удалит.
Prune - дорогой шаг. Он переписывает частично неиспользуемые pack-файлы, а это значит скачать и загрузить их заново, и ему нужна эксклюзивная блокировка, так что пока он работает, ни один бэкап не может запуститься. Его опция --max-unused, по умолчанию 5%, не трогает частично используемые pack-файлы, пока доля мусора не превысит этот порог, - немного места в обмен на гораздо меньший трафик. forget можно запускать хоть каждую ночь, но prune раз в неделю более чем достаточно.
Проверка репозитория#
restic check проверяет структуру репозитория: что дерево каждого снимка полное и что каждый фрагмент, на который есть ссылка, существует в pack-файле, указанном в индексе. Он читает только метаданные и работает быстро.
$ restic check$ restic check --read-data-subset=5%$ restic check --read-data-subset=1/12 # a different twelfth each monthПроверка структуры не доказывает, что данные внутри pack-файлов целы. --read-data скачивает и проверяет всё, а на большом репозитории это много трафика; --read-data-subset читает долю. Ежемесячно сменяемое подмножество n/12 прочитывает весь репозиторий раз в год при двенадцатой части стоимости на запуск.
Восстановление#
Команда, ради которой всё это на самом деле делается:
# Everything from the latest snapshot into a scratch directory$ restic restore latest --target /tmp/restore# One folder from a specific snapshot$ restic restore a81d0b37 --target /tmp/restore --include /srv/minecraft/world# A stdin backup, written back out as a file$ restic dump latest /app.sql > /tmp/app.sql# Browse every snapshot as a filesystem (Linux, macOS with FUSE)$ restic mount /mnt/resticСначала восстанавливайте во временный каталог, проверяйте, затем переносите на место - никогда не восстанавливайте прямо поверх живого сервера: если вы выбрали не тот снимок, это уничтожит улики. latest учитывает --host, --path и --tag, поэтому в репозитории, общем для нескольких машин, используйте restic restore latest --host web-01.
Чтобы восстановить на новую машину, нужны ровно три вещи: эндпоинт, ключи доступа и пароль репозитория. Храните все три там, где они не погибнут вместе с сервером.
Запуск по расписанию#
Скрипт-обёртка, который запускает cron или таймер systemd, сохраняет единообразие задачи:
#!/bin/bashset -euo pipefail. /root/.restic-envrestic backup /srv /etc --exclude-file /root/restic-excludes.txt \ --one-file-system --tag nightly --retry-lock 10mrestic backup --stdin-from-command --stdin-filename app.sql --tag mysql \ --retry-lock 10m -- mysqldump --single-transaction apprestic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 \ --keep-tag locked --retry-lock 10mif [ "$(date +%u)" = 7 ]; then restic prune --retry-lock 30m restic check --read-data-subset=5%fi--retry-lock (restic 0.16 и новее) ждёт снятия блокировки другого процесса, а не падает сразу. Если запуск убит, он может оставить устаревшую блокировку; restic unlock удаляет блокировки, процесса которых больше нет, и его запускать безопасно, а restic unlock --remove-all удаляет все блокировки и безопасен, только когда вы уверены, что больше ничего не работает.
restic держит локальный кэш метаданных репозитория в ~/.cache/restic, что ускоряет каждую операцию. На больших репозиториях он может вырасти до нескольких гигабайт; restic cache --cleanup удаляет кэши репозиториев, которыми вы больше не пользуетесь. Отправляйте вывод скрипта в журнал и настройте оповещение о ненулевом коде выхода - бэкап, который месяц молча падает каждую ночь, - самый частый способ узнать, что бэкапа у вас нет.
Место restic в S3 в плане 3-2-1#
restic делает копию надёжной - зашифрованной, дедуплицированной, проверяемой, - но не может сделать хранилище за ней надёжнее, чем оно есть. S3-хранилище RE:NODE хранит одну копию ваших данных на NVMe в одном месте, без репликации. Это делает репозиторий restic на нём хорошей копией вне машины: отдельно от сервера, который она защищает, в формате, который можно восстановить везде, где работает restic. Но единственной копией это его не делает.
Для данных, которые нельзя потерять, держите второй репозиторий в другом месте и копируйте снимки туда:
$ restic -r s3:https://other-storage.example.net/backups/web-01 \ copy --from-repo s3:https://s3.example.com/my-bucket/restic/web-01 \ --from-password-file /root/.restic-passwordrestic copy переносит снимки между репозиториями, перешифровывая их ключом назначения, и отправляет только те фрагменты, которых в назначении нет. Инициализируйте второй репозиторий через init --from-repo ... --copy-chunker-params, чтобы оба использовали одинаковое разбиение на фрагменты и дедупликация работала между ними. Сколько места нужно каждой копии, разобрано в статье размер хранилища S3 и правило 3-2-1.
FAQ#
Что будет, если я потеряю пароль restic?
Репозиторий не сможет расшифровать никто. Через restic key add можно добавить несколько ключей, каждый со своим паролем, чтобы открыть репозиторий могли больше одного человека или хранилища секретов, - но если потеряны все пароли, потеряны и данные. Храните пароль в менеджере паролей вне сервера.
Почему forget не освободил место?
forget удаляет только записи снимков. Данные, на которые они ссылались, остаются, пока prune не удалит фрагменты, не используемые ни одним снимком. Выполните restic forget ... --prune или после него restic prune.
Могут ли несколько серверов делать бэкап в один репозиторий?
Да, и они дедуплицируются друг с другом, что экономит место, когда у серверов есть общие файлы. Цена - общий риск и общие блокировки: prune блокирует репозиторий для всех машин. Один репозиторий на сервер, каждый в своём префиксе, проще, и именно это предполагается в статье.
restic или rclone?
Они делают разную работу. rclone копирует и зеркалирует файлы; restic делает версионированные, зашифрованные, дедуплицированные снимки со сроком хранения. Для бэкапов с историей используйте restic; для перемещения или зеркалирования файлов - rclone, см. rclone с хранилищем S3.
Сколько места займёт restic?
Примерно объём данных один раз, после сжатия и дедупликации, плюс изменённые фрагменты для каждого сохраняемого снимка. Серверу с 20 GB данных и 1% изменений в день, хранящему 7 ежедневных, 4 еженедельных и 6 ежемесячных снимков, обычно нужно где-то от 25 до 40 GB. restic stats --mode raw-data показывает реальную цифру для вашего репозитория.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.