# Рунбук ПРОД admin.food-market.kz (ALL MARKET) Боевой сервер магазина. Прод-vm **192.168.1.190**, compose **`~/food-market/deploy`**, своя БД **`food-market-prod-postgres:5437`** (НЕ shared-postgres!). gateway nginx (на хосте, только читать) проксирует admin.food-market.kz → :8081 (web). Публичный сайт food-market.kz — НЕ трогаем. ## Чек-лист готовности (выполнено 09.10.2026) - [x] **Образы — релизные теги** (SHA main, не `test`/`latest`): `API_TAG`/`WEB_TAG` в `.env`. - [x] **Секреты прода отдельны от стенда**, в `~/food-market/deploy/.env` **chmod 600**: - `POSTGRES_PASSWORD` — сильный (НЕ dev-дефолт). БД своя (5437). - `OPENIDDICT_ISSUER=https://admin.food-market.kz/`. OpenIddict PFX-ключи генерируются на сервере в томе `food-market-api-data` (очищен перед стартом → свежие прод-ключи, отдельные от стенда/dev). `OPENIDDICT_CERT_PASSWORD` пуст (ключи защищены правами ФС). - `SEED_SUPERADMIN_PASSWORD` — временный, см. ниже. - VAPID (web-push) — автогенерация в БД (PlatformSettings), секрет не нужен. - SMTP — НЕ настроен (задаёт владелец; до настройки сброс пароля по email неактивен). - [x] **Выключено на проде**: quick-login (`QUICK_LOGIN_ENABLED=false` + code safety-override по issuer), стендовые подсказки, демо-сидеры и тест-орги (`SEED_DEMO_DATA=false` → нет «Demo Market»). - [x] **SuperAdmin** `admin@food-market.local` — пароль из `SEED_SUPERADMIN_PASSWORD`; **копия пароля: `~/.fm-watchdog/prod-superadmin-initial.txt` (chmod 600) на dev-vm**. ⚠ Владелец ОБЯЗАН сменить пароль при первом входе (UI → профиль). Рекомендуется также завести персональный аккаунт. - [x] Проверено: вход SuperAdmin через https://admin.food-market.kz = HTTP 200; БД пуста (orgs=0, products=0, users=1=SuperAdmin, roles=4 системных); web SPA = 200; quick-login = 404. ## Деплой прода (ТОЛЬКО вручную) ``` ~/deploy-prod.sh --yes # взять теги из прод .env, backup → up ~/deploy-prod.sh --yes --build # пересобрать+push+деплой с новыми тегами ``` - Скрипт с guard'ами: проверяет что compose = food-market-prod-postgres (не shared-postgres), `.env` chmod 600, НЕ dev-пароль БД, quick-login off, SEED_DEMO_DATA=false, issuer прод. - Делает **бэкап БД ДО** pull/миграций. Миграции применяются автоматически при старте api (`AppDbContext.Database.Migrate()` → `/health/ready` = Healthy только после миграций). - Поднимает `postgres api web` (public НЕ трогает). НЕ в ночных задачах. ## Бэкапы и восстановление - **Ежечасно** (хранение 48 ч): `food-market-backup-hourly.timer` → `/opt/food-market-data/backups/hourly`. - **Ежедневно 03:30** (хранение 30 дн + uploads): `food-market-backup-daily.timer` → `…/backups/daily`; `ExecStartPost` — автопроверка восстановления. - **Офсайт (другая VM)**: dev-vm таймер `food-market-offsite-pull.timer` (04:00) тянет последний daily-дамп на dev-vm `~/fm-prod-backups` (хранение 30 дн). - Формат — `pg_dump -Fc` (pg_restore с параллелизмом/выборочно). - **Проверка восстановления** (вручную): `~/food-market/deploy/prod-restore-verify.sh` — restore последнего дампа во временную БД `food_market_restore_test` + сверка числа строк с боевой + дроп временной. Боевую БД не трогает. Проверено 09.10: все ключевые таблицы совпали. ## Мониторинг - `food-market-prod-monitor.timer` (каждые 5 мин): api `/health/ready`, web, публичный вход, БД (`pg_isready`), место на диске (порог 85%), 5xx в логах api за 5 мин. При проблеме — Telegram владельцу (бот: `~/.fm-watchdog/telegram-{token,chat}` на prod-vm). Лог: `~/.fm-watchdog/prod-monitor.log`. - Тест уведомления: `~/food-market/deploy/prod-monitor.sh --test` (отправлено 09.10 ✓). ## Откат (rollback) 1. Предыдущий образ: в registry по прошлому SHA. `~/deploy-prod.sh --yes` (без `--build`) — вернёт прежние теги (бэкап снимется автоматически до переключения). 2. Данные: восстановить из дампа — `docker exec -i food-market-prod-postgres pg_restore -U food_market -d food_market --clean --if-exists < <дамп>` (на пустую/битую БД; при живой — сначала остановить api). Дампы: `/opt/food-market-data/backups/{hourly,daily}` или офсайт dev-vm `~/fm-prod-backups`. 3. Проверить `/health/ready` и вход. Если проблема в миграции — откат образа на прошлый SHA (миграции в этом проекте аддитивные; down-миграции не применяем на проде). ## НЕ трогать shared-postgres (5434) и его базы (sklad/purchase/calcman/makesales); gateway nginx (только чтение); стенд (test.admin.food-market.kz); публичный сайт food-market.kz (контейнер public, PUBLIC_TAG=test).