Резервные копии и данные

> Кратко. Почти всё, что нельзя потерять, лежит в PostgreSQL: базы городов (вместе с фото нарядов) и UsersDB. Кроме баз копируют .env и переменные служб, каталог данных GeoServer и конфигурацию nginx. Для баз в репозитории API есть скрипт с проверкой и ротацией и задача планировщика к нему.

Читаю как

Что копировать

Что Где Зачем Можно ли восстановить без копии
Базы городов PostgreSQL, список — TGID_CITY_DBS Сеть, расчёты, журналы, наряды и их фото (tgid_work_order_photo), отключения, комментарии, формы, телеметрия, сценарии, ключи встраивания и вебхуки Нет. Сеть можно переконвертировать из десктопа, но всё, что ввели в вебе, пропадёт
UsersDB PostgreSQL, USERS_DB_NAME Пользователи, их права и города, журнал действий Нет
sprav PostgreSQL, SPRAV_DB_NAME Справочники расчёта Частично: движок может читать CSV из sety/sprav
.env API и веба, переменные служб NSSM каталоги API и веба; реестр Services\<служба>\Parameters Пароли баз, JWT_SECRET, хеш мастер-пароля, ключи ИИ и подложек, движок расчёта Нет: без JWT_SECRET все сессии и выданные ключи (API v2, MCP, ArcGIS) станут недействительны
Каталог данных GeoServer на сервере GeoServer Рабочие области городов, слои и SQL-представления, стили Только вручную, долго
Конфигурация nginx каталог nginx Пути городов, проверка входа GeoServer, кеши По образцам scripts/nginx/ в репозитории веба
Функции тайлов martin и его config.yaml MARTIN_SQL_DIR, каталог martin Тайлы сети из PostGIS Да: scripts/martin/build_martin_functions.py и build_martin_config.py
Статичные тайлы PMTiles STATIC_TILES_DIR, по умолчанию files/static_tiles/<город> Здания на встраиваемой карте Да: окно «Статичные слои» или scripts/ops/bake_static_tiles_all.py

Что копировать не нужно:

  • Redis — там очереди и статусы задач;
  • хранилище готовых выгрузок (FILE_STORAGE) — файлы живут FILE_JOBS_TTL, по умолчанию час;
  • кеш тайлов GeoServer (GWC) и nginx;
  • каталог files/kls, files/tab и шаблоны Word — они в репозитории API.

Копии баз и .env содержат персональные данные и секреты. Храните их с тем же ограничением доступа, что и сам сервер — Персональные данные.

Скрипт копирования баз

scripts/ops/backup-city-dbs.ps1 в репозитории API:

  1. Для каждой базы из -Databases и для UsersDB делает pg_dump -Fc в <BackupRoot>\daily\<дата>\<база>.dump. Пишет сначала во временный .part.
  2. Проверяет файл: он не пустой, и pg_restore --list читает его оглавление, то есть файл не обрезан. Только после этого .part переименовывается в .dump.
  3. По воскресеньям копирует дневной каталог в weekly\. Хранит KeepDaily дневных (7) и KeepWeekly недельных (4) копий, более старые удаляет.
  4. С -RestoreCheck <база> восстанавливает свежий дамп во временную базу tgid_restore_check. Сверяет число строк nodes и linesobj с исходной (допуск 1 %) и удаляет временную базу. На время проверки нужно место на диске данных PostgreSQL.
  5. Журнал — <LogDir>\backup-<год-месяц>.log, итог — <BackupRoot>\last-backup.json. Код выхода 1 — была ошибка, её видно в планировщике.

Подключение скрипт берёт из .env API (DB_*, USERS_DB_*). Пароль передаётся только через переменную PGPASSWORD на время вызова и в журнал не пишется.

Список баз. Без -Databases скрипт берёт базы городов из TGID_CITY_DBS в .env API (из одногородского .env — DB_NAME) и добавляет UsersDB, поэтому новый город попадает в копию сам. Нет ни того ни другого — скрипт останавливается с ошибкой. База из списка, которой нет на сервере, — ошибка (код выхода 1, в журнале «ОШИБКА»), а не тихий пропуск. После первого запуска проверьте в last-backup.json, что у каждой базы статус ok.

Задача планировщика. scripts/ops/install-backup-task.ps1 (от администратора) регистрирует две задачи от SYSTEM:

  • «TGID backup» — с понедельника по субботу в 02:30;
  • «TGID backup restore check» — по воскресеньям в 02:30, копия плюс пробное восстановление одной базы (-RestoreCheck auto: базы из того же списка чередуются по номеру недели).

У задач предел 6 часов; если компьютер был выключен, задача запускается при первой возможности. Удалить задачи — Unregister-ScheduledTask -TaskName 'TGID backup', 'TGID backup restore check'.

Скрипт копирует только базы. .env, переменные служб, каталог GeoServer и nginx копируйте отдельно, после каждого их изменения.

Восстановление

  • База города целиком: остановите API и воркеры (или закройте город в nginx), создайте пустую базу и выполните pg_restore -d <база> <файл>.dump. Скрипт проверки восстанавливает с --no-owner --no-privileges. Для рабочей базы с ролями PostgreSQL (AUTH_BACKEND=pg, DB_ROLE_SWITCH) восстанавливайте с правами, иначе пользователи потеряют доступ.
  • После восстановления API сам доведёт схему: недостающие таблицы и функции веба появятся при запуске или в ближайший проход доводки (Несколько городов).
  • UsersDB: после восстановления проверьте версию миграций (alembic current): она должна совпадать с кодом API.
  • Одна таблица или запись: восстановите дамп во временную базу и перенесите нужное запросом. Не восстанавливайте поверх рабочей базы.
  • Кеш тайлов GeoServer после восстановления базы города сбросьте, иначе карта покажет старую сеть до истечения кеша.

Копии для стендов

Отдельного скрипта создания копий в репозитории нет. Копию делают из свежего дампа: pg_restore в базу с суффиксом _copy (almatygid_copy, usersdb_copy). Стенд запускают с .env.copy рядом с .env: в нём только отличия — DB_NAME, USERS_DB_NAME, свой REDIS_DB.

На копии те же персональные данные, что на проде. Стенд с выключенным входом (AUTH_DISABLED=true) показывает их любому, кто его откроет. Держите такие стенды во внутренней сети.

Для разработчика

  • Новая таблица веба в базе города попадает в копию сама. Если она хранит файлы (как фото нарядов), учитывайте размер копии.
  • Новый город — добавить базу в список копирования вместе с TGID_CITY_DBS (Несколько городов).
Хотите увидеть эту функцию на своих данных?Покажем ТГИД на демонстрации и ответим на вопросы инженеров.
Запросить демо