Восстановить хранилище артефактов обычным копированием каталога не получится. Nexus, Artifactory и Docker registry держат полезную нагрузку отдельно от индексов, поэтому без согласованного бэкапа метаданных после восстановления вы получите набор бинарных файлов, который сервис просто не увидит. Рабочая формула выглядит так: выбранная стратегия, подходящий инструмент и регулярная проверка восстановления. Уберите любой из трёх элементов, и защита превращается в иллюзию.
Хранилище артефактов живёт по своим правилам. Пакеты и образы занимают от сотен гигабайт до десятков терабайт, добавляются редко и почти никогда не меняются, а служебные данные (индексы, контрольные суммы, дерево путей, права) меняются постоянно. Полный бэкап такого массива каждый день съедает окно времени и место на диске, а редкий бэкап раздувает разрыв по RPO: момент, после которого данные будут потеряны безвозвратно, отодвигается на сутки и дальше.
Практический вывод прост: для репозиториев до 100 ГБ с редкими изменениями работает ежедневный полный бэкап, для терабайтных хранилищ - комбинация еженедельного полного и ежедневного инкрементного, а снапшоты ZFS дают быструю точку отката между ними. Ниже разобраны стратегии, инструменты и проверка, без которой бэкап остаётся недоказанным.
Почему бэкап хранилища артефактов нельзя свести к копированию файлов
Артефакты полезны ровно настолько, насколько целы сопровождающие их метаданные. В Nexus 3 описания компонентов, привязка к репозиториям и результаты поиска лежат в базе данных PostgreSQL, а в Artifactory старше седьмой версии часть служебных данных хранилась в OrientDB. Docker registry v2 разделяет содержимое на blobs и манифесты с тегами. Скопируйте только каталог с blobs и пропустите базу: после восстановления репозиторий окажется пустым, хотя место на диске будет занято.
Второй момент - согласованность. Репозиторий почти всегда пишется: CI выкладывает новые сборки, планировщик чистит старые снапшоты, клиенты загружают зависимости. Если снимать копию на живой файловой системе, можно поймать состояние на середине транзакции и получить битый артефакт или неполный индекс. Решается это снапшотом тома или краткой остановкой записи на время бэкапа.
Что сохранять: артефакты, метаданные и конфигурации
Минимальный набор объектов для полного восстановления хранилища:
- бинарная нагрузка: blobs Docker registry, pакировании в файловом хранилище (часто каталоги blob store на отдельном датасете);
- база данных с метаданными: PostgreSQL для Nexus 3, встроенная или внешняя БД для Artifactory, база или индекс для других менеджеров репозиториев;
- индексы, контрольные суммы и структура путей, если они хранятся вне базы, в служебных файлах;
- конфигурации: nexus.properties, system.yaml, config.yml реестра, настройки прокси и upstream-репозиториев;
- ключи и сертификаты: TLS-пары, GPG-ключи подписи пакетов, токены сервисных аккаунтов;
- скрипты развёртывания и CI-пайплайны, которые знают, как этот репозиторий поднимается с нуля.
Проверка простая: если на чистом сервере по этим данным невозможно поднять рабочий репозиторий и скачать из него пакет, значит набор неполный. Бэкап базы данных без самих blobs и каталог с blobs без базы одинаково бесполезны.
Риски: от случайного удаления до шифровальщиков
Сценариев потери немного, и все они встречаются в реальной работе. Ошибочный массовый clean-up в веб-интерфейсе удаляет нужный репозиторий; команда удаления по неверному пути на источнике обнуляет каталог; выходит из строя диск или RAID-контроллер; обновление сервиса повреждает схему данных; программа-шифровальщик проходит по смонтированным томам и шифрует доступные для записи копии. Последний сценарий опаснее прочих: если бэкап лежит на том же сервере и доступен на запись из-под той же учётной записи, он будет зашифрован вместе с исходными данными.
Отсюда два правила. Копия хранится на отдельном носителе или площадке, куда основной сервер не имеет прав на удаление. Одна из копий делается неизменяемой (immutable), чтобы её нельзя было перезаписать или стереть в течение заданного срока. Без периодического теста восстановления эти правила остаются теорией, а риск потери данных не снижается.
Стратегии резервного копирования: полный, инкрементный, дифференциальный
Выбор стратегии определяют два параметра: RPO (сколько данных допустимо потерять) и RTO (за какое время сервис вернётся в строй). Частота бэкапа задаёт RPO, а способ хранения копий и скорость восстановления задают RTO.
| Критерий | Полный | Инкрементный | Дифференциальный |
|---|---|---|---|
| Время создания | максимальное | минимальное | среднее, растёт между полными |
| Объём | 100% данных | только изменения с прошлого цикла | изменения с последнего полного |
| Восстановление | один набор | вся цепочка до полного | полный плюс последний диф |
| Зависимость | нет | разрыв цепочки ломает восстановление | зависит от полного |
| Нагрузка на сеть | высокая | низкая | средняя |
Для хранилищ артефактов рабочим вариантом стала гибридная схема: раз в неделю полная копия, ежедневно инкрементная, плюс снапшоты между циклами. Цепочку инкрементов нужно регулярно проверять на целостность: если один сегмент повреждён, восстановление откатится до предыдущего полного бэкапа, и часть свежих артефактов потеряется.
Как выбрать между полным и инкрементным бэкапом
Ориентируйтесь на размер хранилища и темп изменений. Репозиторий до 100 ГБ с десятком новых сборок в день спокойно укладывается в ежедневный полный бэкап: он занимает 15-40 минут и не требует сложной логики ротации. Массив на несколько терабайт с активным CI делает ежедневный полный бэкап бессмысленным по времени и месту, здесь нужен инкремент.
Отдельно про критичные данные: индексы и база метаданных весят немного, поэтому их логично сохранять чаще, чем blobs. Полный дамп базы каждые 4-6 часов занимает минуты, а восстановление после сбоя ускоряет в разы. Тяжёлые blobs при этом уходят в еженедельный полный цикл.
Снапшоты ZFS как быстрый способ зафиксировать состояние
ZFS сохраняет состояние датасета мгновенно, без копирования блоков, за счёт copy-on-write. Снапшот создаётся одной командой:
zfs snapshot tank/artifacts@daily-2026-09-11
Дальше состояние переносится на другой сервер потоком, который передаёт только изменившиеся блоки:
zfs send -i tank/artifacts@daily-2026-09-10 tank/artifacts@daily-2026-09-11 | zfs receive backup/artifacts
Тот же снапшот удобно использовать как точку согласованности: приостановите запись в репозиторий на секунды, снимите снапшот, возобновите работу и копируйте данные уже с неизменяемого среза. Ретенцию удобно держать через sanoid или zfs-auto-snapshot: например, 24 часовых, 14 ежедневных и 8 недельных снимков.
Ограничение у снапшотов одно и жёсткое: они лежат на том же пуле. Потеря пула, сбой контроллера или шифровальщик с правами root уничтожат и данные, и снимки. Снапшоты ускоряют откат, но не заменяют внешний бэкап.
Как строить схемы хранения с ретенцией и расчётом объёма, разобрано в отдельном руководстве по резервному копированию в системах хранения.
Принцип 3-2-1: как применить его к хранилищу артефактов
Правило 3-2-1 требует трёх копий данных, двух разных носителей и одной копии вне основной площадки. Для хранилища артефактов это раскладывается так: рабочее хранилище на ZFS-пуле, локальный бэкап на отдельном сервере или NAS, offsite-копия в S3-совместимом хранилище или на удалённом сервере в другой стойке.
Копии обязательно разносятся по носителям. Два пула в одном шасси не дают защиты от пожара, залива или удара по питанию. Внешний USB-диск с ротацией раз в неделю закрывает часть сценариев, но требует ручных действий и легко забывается, поэтому для артефактов удобнее облачный бэкенд.
Выбор носителей и площадок для копий
Рабочая раскладка для среднего репозитория:
- основное хранилище: ZFS-пул RAIDZ или зеркало на сервере репозитория;
- локальная копия: отдельный сервер или NAS в другой стойке той же площадки, желательно на другом железе;
- offsite: S3-совместимое хранилище (Backblaze B2, провайдерские объектные хранилища) или удалённый сервер;
- архивная копия: холодное хранение раз в месяц для версий, которые уже не нужны в оперативном доступе.
Для offsite-площадки и DR-стенда подходит облачная инфраструктура вроде Timeweb Cloud: там можно держать удалённый сервер с репозиторием снимков и объектное хранилище для копий, оплачивая только занятый объём.
Считайте не только стоимость хранения, но и цену восстановления. Выгрузка нескольких терабайт из облака может занять сутки и больше, а у части провайдеров оплачивается исходящий трафик. Держите рядом с облачной копией свежий локальный снапшот: он закроет быстрый откат, а облако останется на случай потери всей площадки.
Immutable-бэкапы: защита от шифровальщиков
Неизменяемое хранилище запрещает изменять или удалять объект раньше заданного срока. В S3 это Object Lock в режиме compliance или governance: объект нельзя перезаписать даже с полными правами, пока не истечёт срок удержания. Restic и другие инструменты с S3-бэкендом работают с таким хранилищем без изменений, а ключ приложения не может отменить удержание в режиме compliance.
На уровне ZFS аналог даёт команда zfs hold: снапшот с установленной блокировкой не удалится, пока блокировку не снимут вручную. Полезно вешать hold на недельные снапшоты репозитория, чтобы автоматические политики ротации их не затирали.
Ретенцию в restic настраивают так, чтобы она не трогала неизменяемые объекты раньше срока:
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 --prune
Подробный разбор принципа с примерами носителей и настройкой ротации есть в статье про схему 3-2-1 для резервного копирования.
Инструменты для бэкапа: rsync, restic, встроенные механизмы TrueNAS
Три инструмента закрывают почти все задачи, и они не конкурируют, а дополняют друг друга. rsync переносит байты и хорошо подходит для зеркалирования и первичной выгрузки. restic делает версионные бэкапы с шифрованием и дедупликацией, что критично для облака. TrueNAS даёт периодические снапшоты, репликацию и задачи без ручных скриптов.
Настройка rsync для зеркалирования артефактов
Базовая команда зеркалирования каталога артефактов:
rsync -aAXHv --numeric-ids --delete /srv/artifacts/ backup@storage:/backup/artifacts/
Флаги значат следующее: -a сохраняет права, владельцев и время, -A переносит ACL, -X расширенные атрибуты, -H жёсткие ссылки, -v показывает процесс, --numeric-ids не пытается сопоставить пользователей по именам на разных хостах. Флаг --delete удаляет в приёмнике файлы, которых больше нет в источнике, и это главный источник проблем: случайное удаление на источнике мгновенно отражается на копии.
Чтобы сохранить версии удалённых файлов, добавьте отдельный каталог для изменений:
rsync -aAXHv --delete --backup --backup-dir=/backup/versions/$(date +%F) /srv/artifacts/ backup@storage:/backup/artifacts/
Перед первым запуском всегда проверяйте команду в режиме холостого прогона: добавьте --dry-run и посмотрите список операций. Для больших репозиториев полезна опция --exclude-from с перечнем временных каталогов и каталогов загрузок, чтобы не гонять мусор. Автоматизацию удобно вешать на systemd timer или cron, а готовые скрипты и юниты для регулярных запусков собраны в материале про резервное копирование сервера 2026.
rsync не хранит историю версий и не шифрует данные на приёмнике. Если нужна защита от случайных удалений и от чужого доступа к копии, переходите к restic.
Резервное копирование restic: шифрование и дедупликация
Restic шифрует данные на клиенте, поэтому провайдер хранилища видит только зашифрованные блоки. Дедупликация нарезает файлы на блоки и хранит каждый блок один раз, что для репозиториев с повторяющимися пакетами экономит десятки процентов места.
Порядок работы от инициализации до восстановления:
- Пароль хранится в файле с правами 600, путь передаётся переменной окружения RESTIC_PASSWORD_FILE. Потеря пароля означает потерю бэкапа, восстанавливать его нечем.
- Инициализация локального репозитория: restic init --repo /mnt/backup/restic
- Инициализация облачного репозитория: restic init -r s3:s3.amazonaws.com/artifacts-backup, ключи доступа задаются переменными AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY.
- Создание бэкапа: restic backup /srv/artifacts --exclude /srv/artifacts/tmp --tag daily
- Проверка структуры: restic check, полная проверка данных запускается с --read-data-subset=5%.
- Просмотр снимков: restic snapshots --tag daily
- Восстановление: restic restore latest --target /restore/artifacts
Бэкапить нужно не только blobs, но и дамп базы метаданных. Удобный приём: сначала снять дамп PostgreSQL в каталог, затем запустить restic по каталогу артефактов и файлу дампа одной командой, тогда снимок будет целостным по времени.
Задачи TrueNAS и снапшоты ZFS
TrueNAS закрывает рутинную часть без скриптов. Периодические снапшоты настраиваются в разделе задач по расписанию: например, ежечасно с хранением 24 копий, ежедневно с хранением 14 и еженедельно с хранением 8. Задача репликации переносит снапшоты на второй TrueNAS или любой сервер с ZFS по SSH, передавая только изменившиеся блоки.
Для offsite в TrueNAS есть Cloud Sync на базе rclone: каталог артефактов уезжает в S3-совместимое хранилище по расписанию, с шифрованием на стороне клиента при необходимости. Отдельно настройте резервное копирование конфигурации самой системы, иначе после переустановки придётся заново собирать пулы, задачи и права. Инструкция по этому шагу есть в руководстве по резервному копированию конфигурации TrueNAS.
Типичные ошибки при работе с TrueNAS: снапшоты только на одном пуле без репликации, отключённые уведомления о неудачных задачах и хранение пароля restic в открытом виде прямо в скрипте. Восстановление из снапшота делается клонированием датасета или откатом к точке, но откат затрёт данные, созданные после снимка, поэтому для точечного восстановления используйте клон.
Проверка восстановления: обязательный этап, а не опция
Непроверенный бэкап не считается бэкапом. Файл нужного размера в каталоге доказывает только то, что задача запустилась, а не то, что данные читаются. Проверка делится на три уровня по возрастанию строгости.
Методы тестирования: выборочное и полное восстановление
Первый уровень - контроль целостности репозитория. В restic это restic check, а раз в месяц имеет смысл запускать проверку с чтением части данных: restic check --read-data-subset=10%. Команда пересчитывает контрольные суммы и находит повреждённые блоки до того, как они понадобятся в аварии.
Второй уровень - выборочное восстановление. Восстанавливаем случайный артефакт в отдельный каталог и сравниваем контрольные суммы:
restic restore latest --target /tmp/restore-test --include /srv/artifacts/releases/app-2.4.1.jar
sha256sum /tmp/restore-test/srv/artifacts/releases/app-2.4.1.jar /srv/artifacts/releases/app-2.4.1.jar
Суммы должны совпасть. Для Docker registry проверка серьёзнее: поднимаем временный реестр на восстановленных blobs и манифестах и пробуем скачать образ через docker pull. Только успешная выгрузка образа подтверждает, что метаданные и содержимое согласованы.
Третий уровень - полное восстановление на тестовом стенде. Раз в квартал разворачиваем репозиторий из бэкапа на изолированном сервере, поднимаем сервис, скачиваем по одному пакету из каждого крупного репозитория и замеряем реальное время восстановления. Замеренный RTO почти всегда отличается от расчётного, и лучше узнать это на учениях, чем во время аварии.
Методика проверки файлов, баз данных и настроек с оформлением отчёта описана в статье про тестовое восстановление резервной копии.
Чек-лист регулярного тестирования бэкапов
| Проверка | Частота | Что фиксировать |
|---|---|---|
| Логи последнего бэкапа на ошибки | ежедневно | дата, длительность, код возврата, объём |
| restic check или аналог | еженедельно | число повреждённых блоков, статус |
| Выборочное восстановление артефакта | еженедельно | имя файла, совпадение контрольных сумм |
| Доступность offsite-копии | ежемесячно | дата последнего объекта, скорость выгрузки |
| Полное восстановление на стенде | ежеквартально | реальный RTO, найденные пробелы |
| Ротация и сроки хранения | ежеквартально | число снимков, что удалено по политике |
Результат каждой проверки заносится в журнал: дата, кто проверял, что восстановлено, сколько заняло. Журнал превращает бэкап из набора скриптов в управляемый процесс и снимает главный вопрос при аварии: работает ли копия прямо сейчас.
Автоматизация и мониторинг бэкапов
Ручной запуск рано или поздно забудется. Автоматизация сводит работу к трём элементам: расписание, скрипт-обёртка с проверкой кода возврата и оповещение о сбое.
Расписание через cron и systemd timer
Вариант с cron для ежедневного бэкапа в 2 часа ночи:
0 2 * * * /usr/local/bin/backup-artifacts.sh >> /var/log/backup-artifacts.log 2>&1
systemd даёт больше контроля: логи в journal, зависимость от монтирования бэкап-каталога, ограничения по ресурсам. Создаются две единицы: сервис backup-artifacts.service с типом oneshot, который запускает скрипт, и таймер backup-artifacts.timer с расписанием OnCalendar=*-*-* 02:00:00 и Persistent=true. Флаг Persistent важен: если сервер был выключен в момент запуска, задача выполнится после включения, чего cron не умеет без дополнительных ухищрений.
Оповещения об ошибках и метрики
Скрипт-обёртка проверяет код возврата и отправляет уведомление только при сбое, чтобы не заваливать почту успешными отчётами:
- Запускаем бэкап и сохраняем код возврата.
- Если код не ноль, формируем сообщение с хостом, датой и текстом ошибки.
- Отправляем через локальный почтовый агент или Bot API мессенджера.
- Дублируем запись в журнал и завершаемся с тем же кодом, чтобы systemd отметил сбой.
Для метрик подходит textfile collector Node Exporter: скрипт пишет в файл значения вида backup_last_success_timestamp и backup_duration_seconds, Prometheus их забирает, а правило алерта срабатывает, если последний успешный бэкап старше 26 часов. Такая проверка ловит тихие отказы, когда задача формально выполняется, но заканчивается ошибкой и ничего не сохраняет.
Восстановление после сбоя: пошаговый план
Действия при потере данных стоит держать в одном документе рядом с командами, чтобы не искать их под давлением.
- Оцените масштаб: утрачен один репозиторий, датасет или всё хранилище. От этого зависит, восстанавливаете вы снапшот или поднимаете сервис с нуля.
- Определите последнюю целую копию: restic snapshots --tag daily для restic, список задач и снапшотов в TrueNAS для ZFS, даты каталогов версий для rsync.
- Восстановите в отдельный каталог, а не поверх рабочего: restic restore latest --target /restore или zfs clone tank/artifacts@daily-2026-09-10 restore/artifacts.
- Восстановите базу метаданных раньше, чем запустите сервис. Для Nexus порядок такой: поднять PostgreSQL, залить дамп, разместить blobs на месте, затем стартовать приложение.
- Проверьте целостность: скачайте по одному артефакту из крупных репозиториев, для Docker registry выполните docker pull по тегу.
- Запустите сервисы и убедитесь, что CI снова может выкладывать сборки. Зафиксируйте фактический RTO в журнале.
Скрипты восстановления стоит написать заранее и протестировать на стенде: в момент аварии вы будете исполнять проверенную последовательность, а не собирать её по памяти.
Заключение: бэкап как непрерывный процесс
Начните с одного репозитория и одного инструмента. Если хранилище меньше 100 ГБ, поставьте restic с локальным и облачным бэкендом, добавьте restic check в расписание и один раз в неделю восстанавливайте случайный артефакт с проверкой контрольной суммы. Для терабайтных массивов добавьте периодические снапшоты ZFS, задачу репликации на второй сервер и immutable-хранилище для offsite-копии.
Дальше расширяйте: подключите вторую площадку, настройте алерты на устаревший успешный бэкап, заведите журнал проверок и раз в квартал проводите полное восстановление на изолированном стенде. Бэкап работает не тогда, когда он настроен, а тогда, когда из него хотя бы раз успешно подняли сервис.