Настоящий бэкап отличается от игрушечного тремя свойствами: копия шифруется до того, как покинет сервер, физически уезжает в другое место и восстанавливается за приемлемое время, а не в теории. Инструмент restic закрывает все три позиции сам: нарезает данные на чанки, находит повторяющиеся куски и не гоняет их второй раз, шифрует всё на клиенте и складывает в S3-совместимое облако. Свободный проект живёт с 2016 года, пережил моду на десятки конкурентов и остался стандартом для тех, кому нужны копии без отдельной инфраструктуры. Ниже разобрано всё от установки до восстановления: репозиторий, первый бэкап, скорость и сеть, скрипт с ротацией и уведомлением, контроль целостности и типичные ошибки, на которых учиться лучше на чужом опыте.
Чем restic выигрывает у rsync и tar при копировании сервера
rsync копирует файлы, tar упаковывает каталоги, но оба возят повторяющиеся данные целиком. Сегодняшний слепок сервера на 95 процентов совпадает со вчерашним, и логично было бы возить только разницу. restic делает именно так: поток данных режется на чанки переменной длины по содержимому, каждый чанк получает адрес по собственному хешу, и повторяющиеся куски просто не уезжают в облако второй раз. На типовом сервере второй бэкап весит доли процента от первого, и это не премия за тонкую настройку, а поведение по умолчанию с первого дня.
Снапшоты снимают вторую боль. Каждый запуск создаёт снимок со своей датой и временем, внутри он ссылается на общие чанки, а снаружи выглядит полным слепком на момент запуска. Откатиться на вчерашнее состояние можно без распаковки цепочки архивов, как это было в классических инкрементальных схемах, где потеря одного звена рвала всю историю. В restic каждый снапшот самодостаточен: чанки общие, но список файлов полный, и восстановление не зависит от судьбы соседних снимков.
Шифрование происходит на клиенте: ключ существует только у владельца копий, облако видит шум без имён файлов, размеров и структуры каталогов. Целостность встроена в саму модель: каждый чанк проваривается хешем при чтении, а отдельная команда check умеет выборочно перечитывать репозиторий и находить испорченное раньше, чем оно понадобится при аварии. Актуальная сборка на момент подготовки материала имеет номер 0.19.1, формат репозитория давно стабилен.
Установка restic и подготовка бакета S3 с ключами доступа
Установка тривиальна, пакет лежит в штатных репозиториях свежих выпусков Ubuntu и Debian:
apt update && apt install -y restic
restic version
Дальше нужен бакет в любом S3-совместимом хранилище: крупный облачный провайдер, сервис от хостера или собственный MinIO на резервной машине, протокол везде один и тот же. Для бэкапов удобен собственный MinIO ещё и тем, что копии остаются на железе под контролем владельца, а не в чужом аккаунте с чужими лимитами.
Для бакета создаются ключи доступа, и здесь работает правило наименьших привилегий: ключу нужны права чтения и записи только в этот бакет, без доступа к соседним и без права менять настройки. Такой ключ, утёкший со скриптом бэкапа, способен испортить ровно один каталог копий и ничего больше. Отдельно для репозитория придумывается пароль. Пароль это единственный ключ ко всем копиям, его резервная копия хранится отдельно от сервера: менеджер секретов или бумажка в сейфе. Утраченный пароль превращает терабайты копий в шум навсегда, без вариантов и исключений.
Подключение описывается переменными окружения, чтобы команды не приходилось снабжать флагами каждый раз:
export AWS_ACCESS_KEY_ID=КЛЮЧ_ДОСТУПА
export AWS_SECRET_ACCESS_KEY=СЕКРЕТНЫЙ_КЛЮЧ
export RESTIC_REPOSITORY=s3:https://s3.example.com/backup-bucket
export RESTIC_PASSWORD_FILE=/root/.restic-pass
chmod 600 /root/.restic-pass
restic init
Команда init создаёт структуру репозитория и шифрует его метаданные. Повторный запуск на живом репозитории сообщит, что тот уже существует, и это удобная проверка связки до первого бэкапа: если init отчитался об успехе, значит ключи, бакет и пароль работают.
Инициализация шифрованного репозитория и первый бэкап
Первый бэкап забирает всё целиком и потому ходит дольше остальных, дальше пойдут копейки. Список путей выбирается по принципу "чего нельзя пересоздать": конфигурации, данные сайтов, домашние каталоги. Системные пакеты в копию не берут, их ставит менеджер пакетов за минуты, а вот базы данных требуют подготовки: живую базу копировать нельзя, она меняется под руками, поэтому перед запуском restic база выгружается дампом в staging-каталог, и уже дамп уезжает в копию. Стандартная связка: pg_dump или mysqldump в /var/backups/staging, затем restic, затем очистка staging от старых дампов.
restic backup /etc /var/www /root
Вывод честно показывает смысл дедупликации: первый прогон рапортует о добавленных гигабайтах, второй о килобайтах. Полезные фильтры снижают объём ещё на старте: --exclude для кэшей и тяжёлых каталогов, --exclude-caches для папок с меткой кэша, --one-file-system, чтобы случайно не утащить примонтированные разделы вроде сетевых дисков. Список снимков смотрится одной командой:
restic snapshots
Каждому снапшоту приписывается тег, например --tag daily для ежедневных или --tag gold для архивных копий, которые ротация не тронет. Когда снимков станет десятки, теги превратятся в главный способ навигации: свежие ищутся за секунду, архивная полка годовой давности отделяется одним фильтром, а отчёт "что случилось с файлом за месяц" собирается без прокрутки сотни строк.
Скорость, сеть и кэш при регулярных копиях
Первый бэкап упирается в сеть, а не в процессор: шифрование и нарезка на чанки едят единицы процентов современного ЦП, а вот канал до хранилища сразу становится узким местом. Поэтому первый полный прогон разумно запускать ночью или в выходной, когда сайту не нужен аплоад. Все последующие копии переносят только разницу и почти не занимают канал.
restic хранит локальный кэш в домашнем каталоге пользователя, и этот кэш ускоряет повторные операции: индексы репозитория не скачиваются заново. Кэш растёт с числом снапшотов и объёмом данных, и при нехватке места его можно смело чистить, при следующем запуске он соберётся заново. Повреждённый кэш тоже не катастрофа: удаление каталога и повторный прогон возвращают всё в норму.
Когда бэкап делит канал с живым сайтом, скорость ограничивается флагами limit-upload и limit-download, значения задаются в килобайтах в секунду. Тысяча килобайт в секунду оставляет дневному сайту достаточно воздуха, а копия собирается чуть дольше. Полная проверка чтением read-data на терабайтах по узкому каналу займёт дни, поэтому регулярный ритуал строится на выборочном чтении подмножества данных.
Отдельно считается время. Регулярный бэкап на живом сервере выигрывает от расписания, разнесённого с часами пиковой нагрузки: копия в половине третьего ночи не пересекается с вечерним наплывом посетителей, а репетиция восстановления в субботу утром не мешает ночным отчётам. Когда серверов несколько, их окна тоже разносятся по часу, иначе хранилище превращается в бутылочное горлышко в три часа ночи, когда все машины одновременно сдают копии.
Автоматизация через скрипт с расписанием и уведомлением
Ручные копии не живут дольше месяца, автоматизация это часть конструкции, а не украшение. Скрипт собирает всё в одном файле и подходит для типового сервера:
#!/bin/bash
set -euo pipefail
export AWS_ACCESS_KEY_ID=КЛЮЧ_ДОСТУПА
export AWS_SECRET_ACCESS_KEY=СЕКРЕТНЫЙ_КЛЮЧ
export RESTIC_REPOSITORY=s3:https://s3.example.com/backup-bucket
export RESTIC_PASSWORD_FILE=/root/.restic-pass
pg_dump --dbname=site_db --file=/var/backups/staging/site_db.sql
restic backup /etc /var/www /root /var/backups/staging --exclude /var/www/*/cache --tag daily
restic forget --prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-tag gold
restic check --read-data-subset=5%
echo "$(date) restic копия собрана" >> /var/log/restic-backup.log
Скрипт повязывается на расписание одной строкой в crontab:
30 2 * * * /root/restic-backup.sh
Порядок строк в сценарии неслучаен: сначала свежий дамп базы, затем копия, затем ротация с очисткой, в конце выборочная проверка целостности. Строка set -euo pipefail останавливает сценарий на первой ошибке, чтобы тишина в логах не выдавалась за порядок. Уведомление делается любым доступным способом: строка curl на адрес вебхука в конце скрипта сообщит об успехе или провале в тот же момент, а файл лога сохранит историю за месяц. Секреты удобнее вынести в отдельный файл с правами 600 и подключать строкой source, тогда сам скрипт можно показывать коллегам без редактирования.
Ротация снапшотов и контроль целостности репозитория
Политика хранения сводится к набору флагов команды forget, и типовая выглядит так:
- семь ежедневных снапшотов покрывают прошлую неделю;
- четыре недельных держат месяц истории;
- шесть месячных растягивают полгода;
- снимки с тегом gold не ротируются никогда и хранят архивную полку;
- всё, что не попало в правила, удаляется вместе с ненужными чанками.
Команда check заслуживает отдельного ритуала: раз в неделю читаются контрольные метаданные всего репозитория, раз в месяц выборочно перечитываются пять процентов данных. Репозиторий живёт в облаке, облако это чужие диски, и бдительность здесь дешевле восстановления. Список снапшотов с датами и размерами подскажет, если что-то пошло не так: цепочка должна расти ровно, без пропусков и без скачков объёма.
Отдельная мысль про вымогателей, которые зачищают и сами серверы, и доступные копии. Права ключа ограничиваются записью и чтением без права удаления, а политика бакета с версионируемостью объектов превращает репозиторий в цель, которую трудно испортить одной командой. Копия с защитой от удаления стоит конфигурации на десять минут и спасает в сценарии, от которого не спасает ничего другого.
И главное предупреждение для облачных хранилищ: правила жизненного цикла бакета, удаляющие старые объекты по возрасту, ломают репозиторий. Чанки связаны перекрёстными ссылками, удаление даже одного объекта сторонними средствами превращает восстановление в лотерею. Всем удалением внутри репозитория распоряжается только restic, облако хранит и не вмешивается.
Восстановление файлов и типичные ошибки restic
Восстановление целого снапшота это одна команда:
restic restore latest --target /tmp/restore
Слово latest берёт свежайший снимок, вместо него подставляется конкретный идентификатор из списка snapshots. Для точечного восстановления добавляется фильтр пути, и из всего слепка вернутся только нужные файлы:
restic restore latest --target /tmp/restore --include /etc/nginx
restic dump latest /etc/nginx/nginx.conf
Вторая команда вываливает одиночный файл прямо в терминал без распаковки снапшота. Для прогулок по копиям как по обычным каталогам репозиторий монтируется в пустую папку, и вчерашний день соседствует с позапрошлым без единого распакованного гигабайта. Режим требует FUSE и спасает, когда неизвестно, в каком именно снимке нужный файл.
Ошибки предсказуемы и почти всегда самокритичны. Утерянный пароль не лечится ничем, это зашито в архитектуру шифрования. Зависший после прерывания репозиторий отпирается командой unlock, снимающей блокировки после сбоя. Репозиторий открывают той же или более новой версией restic, старая сборка может не знать свежих возможностей формата, поэтому на всех машинах, работающих с копиями, держат одинаковые версии. Облачное хранилище иногда троттлит слишком ретивый сервер, скорость ограничивается флагом limit-upload. А самая коварная ситуация выглядит как успех: правило жизненного цикла в консоли облака молча удалило старые объекты, проверки упали, восстановление стало лотереей.
Копия проверяется репетицией восстановления раз в месяц, иначе это не страховка, а ритуал. restic превращает репетицию в рутину из одной команды, и именно за это его держат годами.