Перейти к содержимому

Резервное копирование и восстановление

Эта инструкция для администратора, который хочет регулярно сохранять Portal и уметь вернуть его после сбоя.

Читайте сверху вниз. На каждом шаге — куда нажать в админке (или какую команду ввести) и что должно получиться.

Кратко про службу в каталоге: portal-backup.


После настройки:

  1. На диске (или NAS) появляются файлы portal-backup-*.tar.gz.
  2. В админке виден журнал: проверка пути, копии, восстановления.
  3. Бейдж Runner online — зелёный, когда процесс бэкапа на связи.
  4. Можно включить ночное расписание или создать копию кнопкой.

ДанныеГде лежатНужно ли
База PostgreSQLБД portalОбязательно
Файлы библиотекS3 bucket portal-filesОбязательно
Лицензия (license.key, install.id)каталог PORTAL_DATA_DIRРекомендуется
Конфигурация.env / portal.env / Helm valuesРекомендуется
Valkey (кэш)кэшНе обязательно — пересоздаётся

ЧастьРоль
Служба Резервное копирование в админкеРазрешает очередь и расписание. Сама архив не пишет
Процесс backup-runnerРаз в ~30 с спрашивает API, делает pg_dump, копирует S3, упаковывает .tar.gz
Runner onlineHeartbeat за последние ~2 минуты (это не то же самое, что «служба включена»)
Журнал на страницеЗаписи validate, backup, restore

В Docker runner обычно поднимается вместе со стеком:

Окно терминала
docker compose up -d
docker compose ps backup-runner
docker compose logs -f backup-runner

Ожидание: контейнер в статусе Up / running. Runner ходит к API через host.docker.internal (Linux Docker Engine 20.10+ и Docker Desktop).


3. Каталог для бэкапов — самый важный момент

Заголовок раздела «3. Каталог для бэкапов — самый важный момент»

Файлы появляются на хосте только если каталог смонтирован в контейнер backup-runner.

В .env задают пару:

ПеременнаяЗначение
PORTAL_BACKUP_HOST_DIRКаталог на хосте (левая часть тома)
PORTAL_BACKUP_MOUNT_PATHПуть внутри контейнера (правая часть тома)

В админке указывают ровно PORTAL_BACKUP_MOUNT_PATH (без / в конце). Другой путь backend и runner отклонят.

Прод на Linux:

PORTAL_BACKUP_HOST_DIR=/var/backups/portal
PORTAL_BACKUP_MOUNT_PATH=/var/backups/portal

В админке: /var/backups/portal.

Dev рядом с compose:

# по умолчанию можно не задавать
# PORTAL_BACKUP_HOST_DIR=./backups
# PORTAL_BACKUP_MOUNT_PATH=/backups

В админке: /backups. На хосте файлы появятся в ./backups.

Dev на Mac (отдельная папка):

PORTAL_BACKUP_HOST_DIR=/path/on/mac/BackupPortal
PORTAL_BACKUP_MOUNT_PATH=/path/on/mac/BackupPortal

Оба значения — один и тот же абсолютный путь. После правки .env:

Окно терминала
docker compose up -d backup-runner backend

Частая ошибка: в админке указали путь Mac/Linux хоста, а в compose смонтирован другой каталог (например ./backups/backups). Журнал покажет «Завершён», но в нужной папке на хосте файла не будет — он останется внутри контейнера.


Страница: Админка → Службы → Резервное копирование → ⚙ Настройки
Адрес: /services/portal-backup.

Два аккордеона:

АккордеонЧто внутри
Резервное копированиеПуть, сколько копий хранить, проверка записи, создание копии, журнал, Runner online
ВосстановлениеСписок успешных копий и постановка restore в очередь

Бейдж Runner online — на этой странице и в Обзор → Обслуживание, не в таблице «Службы».

  1. Войдите как администратор.
  2. Перейдите на /services/portal-backup.
  3. Должны увидеть два аккордеона и журнал.
  1. В блоке Резервное копирование введите каталог.
  2. В Docker — точно значение PORTAL_BACKUP_MOUNT_PATH.
  3. Сохраните.
  1. Нажмите Проверить запись (задание validate).
  2. Файл .tar.gz при этом не создаётся — только проверка, что путь доступен для записи.
  3. В журнале статус должен стать Завершён.
  1. Посмотрите бейдж Backup runner: Online.
  2. Если Offline — см. §8. Обычно помогает docker compose up -d backup-runner.
  1. Нажмите Создать резервную копию.
  2. Появится тост об постановке в очередь.
  3. В журнале — запись backup: В очередиВыполняетсяЗавершён.
  4. На диске (в HOST_DIR) появится portal-backup-*.tar.gz.

Обновляйте журнал (пагинация), пока статус не финальный.

  1. Админка → Службы.
  2. Строка Резервное копирование⋮ → Расписание.
  3. Включите автозапуск и задайте время (после успешного validate и online runner).
СтатусЗначение
В очередиЖдёт runner
ВыполняетсяRunner взял задание
ЗавершёнУспех
ОшибкаRunner сообщил сбой или задание зависло > 30 мин

Архивы пишутся сразу на диск, без очереди админки:

Окно терминала
# Docker-бандл
./portal-cli/portal-cli backup --mode docker --output /mnt/nas/portal-backups
# Native
./portal-cli/portal-cli backup --mode native --output /var/backups/portal
# Kubernetes
./portal-cli/portal-cli backup --mode k8s --output /mnt/nas/portal-backups

Проверка каталога:

Окно терминала
./portal-cli/portal-cli backup validate --path /mnt/nas/portal-backups

Аккордеон Восстановление на /services/portal-backup.

Внимание: восстановление — деструктивная операция. На время работы портал недоступен. Нужны Runner online и отсутствие активного backup/restore.

  1. Откройте аккордеон Восстановление.
  2. В списке — успешные копии с файлом на диске (до 50 шт.).
  3. Выберите копию → подтвердите в модальном окне.
  4. Задание restore попадёт в очередь; runner выполнит восстановление.
  5. Дождитесь статуса Завершён в журнале и проверьте вход на портал.

Восстановление вручную на хосте:

Окно терминала
./portal-cli/portal-cli restore --mode docker \
--file /mnt/nas/portal-backups/portal-backup-20260710-120000.tar.gz --yes

API: Резервное копирование (API).


Portal сам шары не монтирует. Сначала смонтируйте NAS на сервере, затем укажите этот путь в .env и в админке.

Пример Linux:

Окно терминала
sudo mkdir -p /mnt/nas/portal-backups
sudo mount -t cifs //nas.corp/backups/portal /mnt/nas/portal-backups \
-o credentials=/etc/portal/nas.creds,uid=0,gid=0

Затем PORTAL_BACKUP_HOST_DIR / PORTAL_BACKUP_MOUNT_PATH и путь в админке — на этот каталог.


  1. Смотрите логи runner — главный источник:
Окно терминала
docker compose logs -f backup-runner
  1. Запись в БД:
Окно терминала
docker compose exec postgres psql -U portal -d portal -c \
"SELECT id, kind, status, started_at, error_message FROM portal_backups ORDER BY created_at DESC LIMIT 5;"
  1. Задания в running дольше 30 минут backend переводит в Ошибка.

  2. Ручной сброс зависшей записи (только если понимаете, что делаете):

UPDATE portal_backups SET status = 'failed',
error_message = 'Сброс вручную',
completed_at = NOW()
WHERE id = '<uuid>' AND status = 'running';
  1. Сверьте путь в админке с PORTAL_BACKUP_MOUNT_PATH.
  2. Проверьте том: docker inspect portal-backup-runner-1 --format '{{json .Mounts}}'.
  3. Смотрите файлы в HOST_DIR на хосте, а не только путь «внутри» контейнера.
Окно терминала
docker compose ps backup-runner
docker compose up -d backup-runner
docker compose logs --tail 20 backup-runner

После старта бейдж Online обычно появляется в течение ~30 секунд.


portal-backup-YYYYMMDD-HHMMSS.tar.gz
├── manifest.json
├── checksums.sha256
├── postgres.dump
├── s3/portal-files/...
├── portal-data/...
└── config/...

ПеременнаяНазначение
PORTAL_BACKUP_DIRКаталог по умолчанию для portal-cli backup
PORTAL_BACKUP_HOST_DIRКаталог на хосте для тома runner
PORTAL_BACKUP_MOUNT_PATHПуть внутри контейнера (= путь в админке)
PORTAL_BACKUP_RETENTION_COUNTСколько последних .tar.gz хранить (по умолчанию 7)
PORTAL_BACKUP_RUNNER_TOKENТокен X-Portal-Backup-Token для internal API
PORTAL_BACKUP_API_URLURL API для runner (в compose часто через host.docker.internal)

Ручной запуск runner:

Окно терминала
./portal-cli/portal-cli backup-runner
sudo systemctl enable --now portal-backup-runner # native Linux
docker compose up -d backup-runner # docker

В Docker Compose runner ходит к Docker через сервис docker-socket-proxy-backup, а не монтирует /var/run/docker.sock напрямую.


Только если нужен частичный снимок без полного архива Portal.

PostgreSQL:

Окно терминала
# Docker
docker compose exec postgres pg_dump -U portal -Fc portal > portal-backup.dump
# Native
pg_dump -h localhost -U portal -Fc portal > portal-backup.dump

S3 (пример с клиентом MinIO):

Окно терминала
mc mirror portal/portal-files ./backup/portal-files/

  1. Сделайте копию: кнопка в админке или portal-cli backup --output <каталог>.
  2. Обновите: portal-cli upgrade --mode <канал> (см. Обновление).
  3. Проверьте /health и /api/v1/system/version.
  4. При проблемах: portal-cli restore --file <архив> --yes.

  • RPO — сколько данных допустимо потерять при сбое.
  • RTO — сколько времени допустимо на восстановление.
ПрофильRPORTO
Пилот24 ч4 ч
Production1 ч1 ч
Enterprise15 мин30 мин

Настройте Расписание службы в админке или таймер ОС для portal-cli backup под свой профиль.