Разделы документации
ОбзорБыстрый стартРедакции и возможностиМодели и поляРедактор контентаМедиатекаЛокализацияПубликация и работа командыAPI, SDK и генерация типовРасширения и инструментыРабочие проектыЗадания, вебхуки и наблюдаемостьАудит и управление даннымиСоветники и доверие к плагинамКорпоративный входПространства, квоты и масштабированиеCommerce и PortalПрава и безопасностьРазвёртывание и обновленияЛицензии и установка пакетовТекущие ограниченияПомощь и диагностикаДанные в кабинетеCore CMSDeveloper PlatformProduction UseWorkflowOperationsComplianceAI AssistantsPlugin TrustEnterprise IdentityEnterprise ScaleEnterprise DeploymentCommerce BundlePortal BundleNotty CMS DocumentationAuth & SecurityContent ModelingDeploymentEcosystem & Packaging ConventionsEditions and First-party ModulesExtensibilityGetting StartedMedia ManagementModule Extraction PathDraft & PublishUpgrade GuideWebhooks & IntegrationsCookbook: Blog with Next.jsCookbook: Custom PluginCookbook: Multilingual SiteOperations DocsBackup AutomationDeployment BlueprintsRunbook — Восстановление БД из бэкапаRunbook — Плановый деплойRunbook — Реакция на инцидентRunbook — Откат релизаRunbook — Горизонтальное масштабированиеRunbook — Ротация секретовRunbook — Major upgradeSecrets ManagementNotty CMS — Capability MapNotty Configuration ModelGenerated App ContractComponents and Dynamic ZonesMiddleware SystemPerformance & Scaling ToolkitDisaster Recovery PlaybookDistribution Model
Документация / Технический справочник

Backup Automation

Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.

По функциям модуляОбновлено 2026-09-30

Документ описывает автоматизированный backup-контур Notty CMS поверх встроенного backup API (packages/server/src/lib/backup.ts, /api/admin/backups*). Цель — RPO в часах, off-site копии и проверяемый restore, без ручных шагов в обычной жизни.

Что бэкапится

Notty backup snapshot включает (по флагам):

  • schemas — content-type схемы и расширения.
  • components — компоненты и dynamic zone определения.
  • config — admin settings, API tokens metadata, webhook конфиги.
  • content — записи всех content types.
  • media — метаданные media-library + сами файлы (если storage поддерживает чтение через провайдер).

Snapshot создаётся на стороне сервера и регистрируется в backup catalog; данные файла хранятся через текущий storage provider. Это не замена pg_dump — для DR-уровня managed Postgres + его собственный PITR остаются обязательными. Backup API закрывает application-level снимок, согласованный по schemas/content/media.

Слои защиты

1. Managed PG snapshots (PITR, daily, инфра-уровень)         ← обязателен
2. Notty application backups (Notty backup API, расписание)  ← основное
3. Off-site copy в S3 / Glacier / GCS Coldline               ← на случай region failure
4. Quarterly restore drill                                    ← подтверждает работоспособность

Не пропускайте ни один слой: managed PG спасёт от аппаратной потери, Notty backup — от логических ошибок (например, удалили content type), off-site — от региональной катастрофы, drill — от того, что бэкапы не восстанавливаются.

Расписание

docker-compose / VM

# /etc/cron.d/notty-backup
0 2 * * * notty BASE_URL=http://127.0.0.1:2102 \
  ADMIN_TOKEN_FILE=/run/secrets/notty_admin_token \
  /opt/notty/deployment/scripts/backup.sh \
  >> /var/log/notty/backup.log 2>&1

Скрипт deployment/scripts/backup.sh:

  • ходит в POST /api/admin/backups синхронно;
  • принимает ADMIN_TOKEN или ADMIN_TOKEN_FILE;
  • считает 2xx-ответ как успех;
  • при заданном BACKUP_S3_BUCKET копирует *.response.json на S3 (для audit/restore handoff);
  • сам чистит локальные ответы старше RETENTION_DAYS (snapshot'ы внутри Notty чистит встроенный backup.cleanup job).

Kubernetes

deployment/kubernetes/cronjob-backup.yaml — CronJob 0 2 * * *, concurrencyPolicy: Forbid, Forbid-overlap, successfulJobsHistoryLimit: 3.

Прокидывает NOTTY_ADMIN_TOKEN из notty-secrets. Это должен быть API token, созданный super-admin пользователем со scope admin:backups:write или admin:*. Failure → стандартная алёртинг-цепочка k8s (Prometheus alertmanager на kube_job_failed).

Через встроенный scheduler Notty

Альтернативно (без внешнего cron'а) — встроенный POST /api/admin/backups/schedule:

curl -X PUT "$BASE_URL/api/admin/backups/schedule" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": true,
    "cronExpression": "0 2 * * *",
    "retentionDays": 30,
    "sections": {
      "schemas": true, "components": true,
      "config": true,  "content": true, "media": true
    }
  }'

Подходит для single-instance: расписание исполняется in-process. Для k8s стоит предпочесть внешний CronJob, чтобы запуск не зависел от того, какой именно pod лидер scheduler'а.

Retention

Слой Default retention Где меняется
Notty backup catalog 30 дней retentionDays в API/расписании
Off-site (S3 lifecycle) 90 дней + Glacier bucket lifecycle policy на стороне cloud
Managed PG PITR 7-35 дней настройки provider'а
Quarterly archive 1 год вручную помечайте важные snapshot'ы как keep

Off-site копия

Стратегии:

  1. Через storage provider. Если STORAGE_TYPE=s3, и snapshot bytes складываются в media-bucket — настройте cross-region replication на bucket'е. Простейший путь.
  2. Pull от backup-runner'а. CronJob, которого нет в Notty: ходит в backup API, выгружает архив (когда такой endpoint включён в вашей сборке) и копирует в отдельный архивный bucket.
  3. pg_dump в архив. Параллельный CronJob, который снимает application- independent dump и кладёт его в Coldline/Glacier. Самый «тупой и надёжный» вариант.

Минимум — стратегия 1 + managed PG PITR.

Verification (drill)

Каждый квартал, plus после крупного апгрейда:

  1. Возьмите non-prod кластер.
  2. Запустите deployment/scripts/restore.sh --dry-run против последнего snapshot'а — проверьте, что dry-run возвращает success: true без diff'ов schema-mismatch.
  3. Затем без --dry-run. Замерьте RTO.
  4. Прогоните smoke (deployment/scripts/verify-deploy.sh) и базовые critical path сценарии: логин, чтение и публикация content type, media upload.
  5. Зафиксируйте результат в docs/testflow/runs/<date>-restore-drill/.

Если drill не сошёлся — заведите инцидент. Бэкап считается рабочим только после успешного drill.

Алёрты

Минимальный набор PromQL-алёртов (см. docs/observability/):

# Бэкап CronJob упал
ALERT NottyBackupJobFailed
  IF kube_job_failed{job_name=~"notty-backup-.*"} > 0
  FOR 10m

# Backup catalog не пополняется
ALERT NottyBackupStale
  IF (time() - notty_last_backup_completed_seconds) > 60*60*36   # >36ч
  FOR 30m

Метрика notty_last_backup_completed_seconds поднимается в lib/backup.ts после успешного снимка (если в вашей сборке метрик она не экспортируется — заведите алёрт по логам или используйте kube_job_status_succeeded как прокси).

DR / Restore

Сценарий восстановления — отдельный документ: runbooks/database-restore.md. Он покрывает выбор snapshot'а, dry-run, full restore и post-validation.

Источник: docs/operations/backup-automation.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.