Files
backup-master/docs/DESIGN.md
T
mrleo1nidandClaude Opus 5.5 1d44d067e9 backup-master: сервер бэкапов, агент и восстановление VPS
Один бинарник backupctl:
- server: API для агентов и restore, веб-морда (один админ), SQLite,
  ретеншн GFS, heavy-части, уведомления ntfy, раздача agent.sh/restore.sh;
- backup/plan: сбор по каталогу категорий (files/systemd/xui/compose),
  горячие дампы Postgres/Mongo/MySQL, снимок x-ui.db, docker-тома,
  digest образов, проверка crontab, потоковая отправка tar.zst;
- restore: провижининг на основе vps_installer с теми же версиями пакетов,
  recipes 3x-ui/nebula/sing-box нужных версий, восстановление compose
  с заливкой дампов и закреплением образов по digest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:52:40 +03:00

6.1 KiB
Raw Permalink Blame History

Устройство backup-master

Компоненты

Старый сервер                     Сервер бэкапов                     Новый сервер
backupctl backup ──PUT части──►   backupctl server                ◄── backupctl restore
 (systemd timer)                  SQLite + файлы, веб-морда            provision.sh → recipes → распаковка → сервисы
                                  ретеншн, ntfy
Пакет Назначение
internal/manifest формат манифеста бэкапа (общий для всех)
internal/catalog категории бэкапа: встроенный default.yaml + переопределения клиента
internal/archive tar (PAX) + zstd: запись, распаковка, исключения, владельцы по имени
internal/api протокол и HTTP-клиент
internal/agent сбор: files / systemd / xui / compose, дампы, проверка crontab, отправка
internal/restore восстановление: provision.sh, recipes бинарников, compose, порядок категорий
internal/server API, веб-морда, ретеншн, уведомления

Формат архива

Каждая часть — tar.zst. В main первой записью идёт manifest.json. Пути внутри архива:

  • <cat>/files/<абсолютный путь> — восстанавливается в /;
  • <cat>/dumps/<файл> — дампы БД и снимок x-ui.db;
  • <cat>/volumes/<том>/… — именованные docker-тома;
  • <cat>/bin/<абсолютный путь> — fallback-копии бинарников.

Heavy-часть называется именем категории и устроена так же. Main без неё самодостаточен.

Протокол

Метод Токен Назначение
GET /api/v1/agent/config агент домен, переопределения каталога, пора ли слать heavy
POST /api/v1/backups агент манифест → id
PUT /api/v1/backups/{id}/parts/{name} агент потоковая загрузка части
POST /api/v1/backups/{id}/complete агент sha256/размеры частей + предупреждения архивации
POST /api/v1/backups/{id}/fail агент ошибка
GET /api/v1/restore/manifest[?backup=] restore манифест и доступные части
GET /api/v1/restore/{id}/parts/{name} restore скачивание (Range — докачка)

Агентский токен даёт только запись: если клиента взломают, злоумышленник не сможет прочитать или удалить его историю. Restore-токен выпускается в морде на 24 часа и даёт только чтение бэкапов одного клиента. В БД хранятся только sha256 токенов.

Агент архивирует часть прямо в тело PUT (io.Pipe), временный архив на диске не создаётся. Дампы БД снимаются до архивации. Поэтому в Stoat порядок «сначала mongodump, потом файлы MinIO» соблюдается сам собой: файлы, загруженные во время бэкапа, станут лишними объектами без ссылок, но ссылок на отсутствующие файлы не появится.

Compose

  • Проекты берутся из docker compose ls -a, к ним добавляются явные dir из каталога. Сервисы, bind-mounts и тома — из docker compose config --format json.
  • БД определяются по образу. Если контейнер запущен, делается дамп через docker exec: учётные данные берутся из окружения контейнера, а каталог данных исключается. Если остановлен — каталог данных копируется как есть (он консистентен).
  • Данные rabbitmq и сервисов из skip_services не бэкапятся.
  • Записываются digest запущенных образов. При восстановлении создаётся compose.restore.yml с image: repo@sha256:…, потому что latest на новом сервере дал бы другую Mongo/MinIO.
  • Отсутствующие external-сети создаются пустыми. Так stoat-mbot поднимается без psiphon.
  • Порядок восстановления: pull → build → create → для каждой БД up -d <db> → ожидание TCP-готовности → заливка дампа → up -d.

Версии

Что Как записывается Как восстанавливается
apt-пакеты (caddy, telegraf, docker-ce, docker-compose-plugin) dpkg-query provision.sh ставит pkg=version, если версия есть в репозитории
3x-ui, nebula, sing-box-extended version_cmd recipes в internal/restore/recipes.go: release-архивы нужного тега; при неудаче — копия из bin/
образы compose digest compose.restore.yml

Расширение

  • Новая категория — запись в default.yaml или в YAML клиента в морде.
  • Новый способ установки бинарника — функция в recipes, имя указывается в поле install категории.
  • Новый тип БД в compose — dbKind/dumpCmds в internal/agent/compose.go и dbReady/dbRestore в internal/restore/compose.go.