💾 Play-API — резервное копирование и восстановление
О чём это
После переезда в Oracle Cloud база
playперестала быть локальной, и старый бэкап её потерял. Здесь — как устроена текущая схема, почему она именно такая, и как проверить, что бэкап живой.
Направление: тянем, а не пушим
Postgres на Oracle намеренно не публикует порт — в docker-compose.yaml прямо сказано «No ports are published: it is reachable only as db:5432». Поставить туда агент домашнего бэкап-сервера тоже нельзя: агент ходит к серверу домой, а домашний NAT входящие соединения не пропускает.
Поэтому направление развёрнуто — aurora тянет с Oracle:
oracle (play-api)
▲ ssh, forced command
│
aurora ──▶ ~/db-backups/ ──▶ BBS-агент ──▶ Borg-репозиторий на dexus
(pre-backup hook) 01:00
Так у публичной VM нет ни ключей от хранилища, ни маршрута в домашнюю сеть: её компрометация не даёт доступа к архивам.
Почему не VPN
Обсуждали site-to-site между домашним MikroTik ax3 и Oracle. Отвергли: туннель дал бы публичной VM маршрут в домашнюю LAN, не решив ничего, чего не решает pull по SSH.
Что именно забирается
На Oracle стоит /usr/local/bin/play-backup-export, привязанный к ключу через command="…",restrict — shell по этому ключу недоступен, принимаются только три глагола:
| Глагол | Команда | Файл на aurora |
|---|---|---|
db (и пустая команда) | pg_dump -U play -Fc -Z0 play | play.dump |
globals | pg_dumpall -U play --globals-only | play.globals.sql |
cfg | tar с .env + docker-compose.yaml | play-config.tar (права 600) |
Три причины, почему именно так:
-Z0(без сжатия) — чтобы Borg дедуплицировал дамп против предыдущих ночей. Сжатый дамп меняется целиком от любого различия и ложится в репозиторий заново каждый раз.globalsотдельно —pg_dumpне выгружает роли. Кластер, восстановленный из одногоplay.dump, поднимется вообще без логинов.cfg—.envсамая невосстановимая часть стека: этих значений нет ни в репозитории, ни в документации (см. предупреждение в заметке о переезде про забытые переменные).
Схема play, а не public
Таблицы лежат в схеме
playЭто уже подводило дважды.
pg_dump -t botsбез схемы тихо возвращаетno matching tables were found, а проверкаinformation_schema.tables where table_schema='public'показывает 0 таблиц на полностью корректном восстановлении.Правильно:
-t play.bots, а для подсчёта —select count(*) from play.gamesлибо агрегат по всем несистемным схемам.
Это же делает неприменимым встроенный плагин BBS «PostgreSQL Backup/Restore»: его рекомендованная роль выдаёт гранты на public, то есть дамп получился бы без данных. Плюс плагин требует TCP-доступа к базе (пришлось бы выставлять Postgres в интернет) и сжимает дамп, ломая дедупликацию. Осознанно остались на Shell Script Hook.
Проверка, что бэкап живой
Зелёный лог ≠ рабочий бэкап
С 27 июля по 2 августа 2026
play.dumpне обновлялся шесть суток, при этом агент каждую ночь писалPre-script completed successfully (exit 0), а Borg исправно архивировал протухший файл как свежий.Причина составная: удалённый fetch намеренно не фатален (сбой в сети не должен ронять локальные дампы), stderr уходил в
/dev/null, а единственный сигнал — pushstatus=downв Uptime Kuma — остался незамеченным.
Что теперь ловит такую ситуацию:
check_freshвbackup.sh— артефакт старше 36 часов считается провалом. Возраст файла переживает любую причину сбоя, в отличие от кода возврата.~/verify-play-restore.sh(crontab пользователяjegors, воскресенье 04:00 UTC) — поднимает одноразовый Postgres, реально восстанавливаетplay.dump, проверяет схему и падение числа строк относительно прошлого прогона. Лог —~/verify-play-restore.log.- stderr больше не глушится и попадает в лог-строку
backup.sh, а оттуда в/var/log/bbs-agent.log.
Восстановление вручную
# 1. Достать артефакты из Borg (или взять свежие из ~/db-backups на aurora)
# 2. Роли — первыми, иначе объекты не к кому привязать
docker exec -i <pg> psql -U postgres -d postgres < play.globals.sql
# 3. Сама база
docker exec -i <pg> pg_restore -U postgres -d play --no-owner --no-privileges < play.dump
# 4. Проверка — именно по схеме play
docker exec <pg> psql -U postgres -d play -Atc "select count(*) from play.games"
# 5. Конфиг
tar -xf play-config.tar -C /opt/play-cloudПроверено вживую 2026-08-02: восстановление дало 8 таблиц и 53 709 партий.
Где что лежит
| Что | Где |
|---|---|
| Экспортёр (forced command) | Oracle: /usr/local/bin/play-backup-export |
| Ключ доступа | aurora: ~/.ssh/oracle-play-backup |
| Pre-backup hook | aurora: ~/backup.sh (запускает bbs-agent от root в 01:00) |
| Артефакты | aurora: ~/db-backups/ |
| Проверка восстановления | aurora: ~/verify-play-restore.sh |
| Лог агента | aurora: /var/log/bbs-agent.log (не journal; время в UTC) |
| Архивы | dexus: /mnt/backup, репозиторий dexus-backup-hdd |
Полная домашняя картина (PBS, BBS, расписания всех клиентов) — в вики homelab, заметка «Глобальная стратегия резервного копирования».