🏦 Capital - архитектура продакшен-инфраструктуры

Версия 1.0 - 15.09.2026 - CTO-план Продукт: core-banking платформа Capital (bo. / app. / kyc. algorys.cc) Подготовлено: CTO (Claude) по итогам совета с внешними консультантами (Grok reasoning + GPT), референс - платформа Iorys.


1. 📌 Резюме для CEO

Продукт функционально готов (183 автотеста, AML/KYT, 4-eyes, 2FA, аудит), но инфраструктура - стартаперская: всё живёт на одном шаредном сервере вместе с Nextcloud, и у базы данных нет ни одного бэкапа. Любой отказ диска = полная потеря банка.

Целевое состояние достижимо за ~2-4 рабочих дня критики + месяц доводки, бюджет ~$60-80/мес (профи-вариант ~$130-150/мес). Ни один компонент не стоит «тысячи долларов».

Три главных решения: 1. 🖥 Capital переезжает на собственный выделенный сервер (team-nextcloud остаётся файловым сервером команды - его не трогаем). 2. 💾 Бэкапы прежде всего: pgBackRest + WAL-архивация в два независимых хранилища, шифрование age, автоматический еженедельный restore-тест. RPO ≤ 5 минут. 3. 📈 Мониторинг + staging + CI/CD-деплой - чтобы выглядеть и работать как банк, а не как pet-проект.


2. 🔍 Текущее состояние (as-is) и точки отказа

Компонент Сейчас Риск
Сервер 1 шаредный VPS (вместе с Nextcloud), 75GB 🔴 единая точка отказа всего банка
Postgres 1 контейнер, 1 volume 🔴 отказ диска = потеря всех данных
Бэкапы БД отсутствуют 🔴 критично, риск №1
Деплой rsync с dev-машины + build на проде 🟠 нет воспроизводимости, нет отката
Секреты .env chmod 600 🟠 без версионирования/шифрования
Мониторинг только Docker healthcheck 🟠 о падении узнаём от клиента
Cloudflare tunnel 1 connector 🟡 перезапуск = недоступность
Документы клиентов BLOB в Postgres (cap 5MB) 🟡 раздувает БД и бэкапы
Что уже хорошо CF proxy + скрытый origin, HMAC-вебхуки fail-closed, 2FA, RBAC, CSRF, rate-limit, аудит-лог, Alembic, git-remote

3. 🗺 Целевая топология (to-be)

                        Интернет
                           |
                 [Cloudflare: WAF/proxy/tunnel]
                    (2 connector'а cloudflared)
                           |
        +------------------+------------------+
        |                                     |
  🖥 capital-prod (Hetzner, NEW)        🖥 capital-ops (Hetzner, NEW)
  CCX23: 4 vCPU ded / 16GB / 160GB      CX22 + volume 100GB
  - backoffice / cabinet / kyc          - staging (тот же compose, throwaway-БД)
  - Postgres 16 (WAL-архивация)         - Uptime Kuma (внешний надзор за prod)
  - pgBackRest (клиент)                 - pgBackRest repo-зеркало + restore-тест
  - Netdata, node-alerts → Telegram     - Netdata
        |                                     |
        +----------- бэкапы (age) ------------+
                           |
        ☁️ Backblaze B2 (EU, Object Lock/WORM)   - копия №1 off-site
        ☁️ Hetzner Storage Box 1TB               - копия №2 off-site
                           |
        team-nextcloud - ОСТАЁТСЯ как файл-сервер команды.
        Capital с него уезжает целиком (переезд = первый DR-тест).

Принципы распределения рисков: - Prod и ops/staging - разные серверы в разных дата-центрах Hetzner (Nuremberg / Falkenstein). - Бэкапы - в двух независимых хранилищах у двух разных провайдеров (B2 + Storage Box), обе копии зашифрованы age, ключ расшифровки НЕ на prod-сервере. - Мониторинг prod живёт НЕ на prod (ops-сервер видит падение prod снаружи). - HA-кластер (Patroni и т.п.) сейчас НЕ нужен - на нашем масштабе правильнее быстрый DR (восстановление ≤ 2-4 ч), это в 10 раз дешевле и проще. - Managed Postgres не берём: дороже, меньше контроля для аудита; self-hosted + PITR на этом масштабе надёжнее по цене/качеству (консенсус обоих консультантов).


4. 🗄 Хранение данных

Данные Где Политика
Операционные (клиенты, счета, платежи, ledger) Postgres 16 на capital-prod WAL-архивация каждые ≤5 мин, PITR
Документы клиентов (KYC-файлы) поэтапно: Postgres BLOB → Backblaze B2 (шифрование age, в БД - только метаданные + ключ объекта) миграция в месяц 1
Аудит-лог append-only схема в Postgres + hash-chain (каждая запись несёт хэш предыдущей - доказуемая неизменность) ежедневный дайджест → B2 c Object Lock (WORM)
Retention (комплаенс) операционные + аудит: 7 лет; AML/KYT-материалы: 10 лет закрепить в политике
Секреты sops + age в git (зашифрованы) + runtime через .env/Docker secrets ключ age - только у CEO + на prod

Postgres-настройки банковского уровня: wal_level=replica, archive_mode=on, wal_compression, archive_command → pgBackRest; контрольная запись LSN перед каждой миграцией.


5. 💾 Бэкапы и Disaster Recovery (правило 3-2-1)

Инструменты: pgBackRest (БД) + restic (конфиги/файлы), всё шифруется age.

Что Частота Куда
Full-бэкап БД ежесуточно 03:00 UTC B2 + Storage Box
Incremental каждые 6 ч B2
WAL-архив (PITR) непрерывно, ≤5 мин B2
Конфиги/compose/секреты (sops) ежесуточно B2 + Storage Box
Копия №2 всего еженедельно Storage Box (независимый от B2)

Целевые показатели: RPO ≤ 5 минут (теряем максимум 5 минут данных), RTO ≤ 2-4 часа (полное восстановление банка на новом сервере).

Restore-тест - автоматический, еженедельный: ops-сервер разворачивает бэкап в изолированный контейнер, проверяет pg_isready + контрольные суммы ключевых таблиц, шлёт отчёт в Telegram. Бэкап, который не восстанавливали, - это не бэкап.

DR-ранбук (документируется в репо): заказ нового сервера → restore из B2 → deploy образов из GHCR → перевод Cloudflare tunnel → смоук-тест. Прогоняем учения раз в квартал.

Мониторинг бэкапов: каждая джоба пингует Healthchecks.io - если бэкап НЕ прошёл, алерт в Telegram (отсутствие сигнала = тревога, а не тишина).


6. 📈 Мониторинг и алертинг (всё бесплатное)

Слой Инструмент Где $/мес
Uptime всех URL + партнёрских API Uptime Kuma ops-сервер 0
Метрики хоста/контейнеров/Postgres Netdata оба сервера 0
Ошибки приложений (stack-traces) Sentry free tier SaaS 0
Cron/бэкап-джобы Healthchecks.io SaaS 0
Дашборды/логи (по мере роста) Grafana Cloud free SaaS 0

Все алерты - в Telegram, три канала: 🔴 critical (будим CEO), 🟠 warning, 🔵 backup/report. Внешняя status-page (BetterStack free / GitHub Pages) - вне Cloudflare, чтобы работала даже при падении CF.


7. 🔐 Безопасность (поверх уже сделанного)

  1. Hardening-стандарт группы на оба новых сервера с первого часа: SSH только через Tailscale, ufw deny inbound, fail2ban, unattended-upgrades, Telegram-алерт на SSH-вход (с анти-спамом), порты приложений только на 127.0.0.1, Docker без privileged.
  2. Секреты: sops + age (конфиги в git зашифрованы, расшифровка только на серверах); значения впрыскиваются оператором мимо чата - как заведено.
  3. CI-сканеры (все бесплатные): gitleaks (секреты в коммитах), Trivy (уязвимости образов), Dependabot (зависимости), CodeQL.
  4. Доступы: GitHub - protected main + обязательная 2FA; Tailscale ACL - prod видит только CEO и деплой-ключ; ревизия доступов раз в квартал.
  5. Incident Response план (короткий документ): кто, что, в каком порядке при инциденте: изоляция → оценка → восстановление → пост-мортем → уведомления клиентам.
  6. Внешний pentest - 1 раз в год (~$2-3.5k разово, закладываем в бюджет квартала, обязателен перед активными продажами и для партнёров/регуляторов).
  7. Graceful degradation при отказе партнёров (частично уже в коде): rail недоступен → платёж в pending_partner, клиент видит «принят, в обработке», ledger не финализируется; SumSub упал → заявка сохраняется draft; Resend упал → email-очередь с ретраями. Клиент никогда не видит ошибку 500 вместо статуса.

8. 🚀 Деплой-пайплайн (уходим от rsync)

git push → GitHub Actions: тесты (183) + сканеры → сборка образов → GHCR
  → авто-деплой на staging (ops) → смоук-тест
  → ручное подтверждение → деплой на prod (docker compose pull && up -d)

9. 🧯 Матрица отказов

Отказ Клиент видит Наши действия Время
capital-prod умер страницу тех-работ (CF) DR: новый сервер + restore из B2 + перевод tunnel ≤ 2-4 ч
Диск/данные повреждены тех-работы PITR на момент до сбоя ≤ 2-4 ч, потеря ≤ 5 мин
Cloudflare упал недоступность status-page вне CF; ждём CF (SLA выше нашего не обещаем) по CF
Rail-партнёр упал «платёж в обработке» очередь pending_partner, ретраи, алерт авто
NS Cards упал «операция ожидает» pending_external, reconcile-джоба авто
SumSub упал заявка сохранена pending_provider, ретраи вебхуков авто
Resend упал письмо позже email-очередь, ретраи авто
ops-сервер умер ничего (prod живёт) пересоздать ops по ранбуку ≤ 1 день

10. 🗓 Roadmap внедрения

Неделя 1 - «перестать жить без бэкапов» (2-4 рабочих дня)

  1. Заказать capital-prod + capital-ops (Hetzner API), hardening с первого часа.
  2. pgBackRest + WAL → B2 + Storage Box, age-шифрование, Healthchecks-пинги.
  3. Переезд Capital на capital-prod (по сути - первый DR-тест: restore из бэкапа).
  4. Uptime Kuma + Netdata + Telegram-алерты.
  5. Первый ручной restore-тест - убедиться, что восстановление реально работает.

Месяц 1 - «профессиональная база» (1-2 недели работ)

  1. GitHub Actions CI/CD + GHCR + staging на ops.
  2. sops + age для секретов; сканеры gitleaks/Trivy/Dependabot в CI.
  3. Sentry + автоматический еженедельный restore-тест.
  4. Миграция документов из BLOB → B2; второй cloudflared connector.
  5. DR-ранбук + первые учения; IR-план; hash-chain аудита + WORM-дайджесты.

Квартал 1 - «зрелость» (3-5 недель суммарно)

  1. Blue-green деплой, status-page, второй email-провайдер (резерв).
  2. Квартальные DR-учения + security tabletop.
  3. Внешний pentest (перед активными продажами).
  4. Формальный risk-register + политики (backup/retention/access/change) - партнёры и регуляторы такое спрашивают.

11. 💰 Бюджет

Базовый (рекомендую стартовать с него)

Компонент Продукт $/мес
Prod-сервер Hetzner CCX23 (4 vCPU ded, 16GB, 160GB) ~33
Ops/staging-сервер Hetzner CX22 + volume 100GB ~12
Бэкап off-site №1 Backblaze B2 (Object Lock) ~3-6
Бэкап off-site №2 Hetzner Storage Box 1TB ~4
Мониторинг/ошибки/CI/WAF/VPN Uptime Kuma, Netdata, Sentry, Healthchecks, Grafana Cloud, GitHub Actions, Cloudflare, Tailscale - все free-tier 0
Итого ~$52-55/мес

Профи-апгрейд (когда пойдут клиенты)

Добавка Зачем $/мес
Cloudflare Pro расширенный WAF/правила 25
Sentry Team больше ошибок/ретеншн ~26
Healthchecks/BetterStack paid больше проверок ~5-10
GitHub Team + Tailscale Starter орг-контроли доступа ~20
Итого профи ~$130-150/мес

Разовые: внешний pentest ~$2-3.5k/год (квартал 1+).


12. 🤝 Что нужно от CEO

  1. 🔑 Hetzner API token (проект для Capital) - закажу и настрою оба сервера сам, мимо UI.
  2. 🔑 Backblaze B2 - аккаунт (или создаём новый), ключ сгенерирую на стороне сервера мимо чата.
  3. ✅ Утвердить бюджет (~$52-55/мес база) и переезд prod на выделенный сервер.
  4. 💳 (Отдельный трек) Оплата инвойсов Papaya и NS Cards - для флипа симуляторов на live.
  5. 🔒 Age-ключ восстановления бэкапов - сгенерирую, приватная половина хранится у CEO (не на серверах): без него бэкапы не расшифровать, с ним банк восстанавливается даже при потере всего.

13. 📎 Приложение: сводка мнений консультантов

Вопрос 🛰 Grok (reasoning) 🤖 GPT Решение CTO
Серверов 3 (prod + DR/staging + backup-node) 2 (prod + ops) 2 - backup-node избыточен, его роль закрывают B2+Storage Box
Postgres self-hosted + hot-replica сразу self-hosted, warm standby позже self-hosted, replica позже - на пилоте DR за 2-4 ч достаточен
Деплой Coolify (PaaS-панель) GitHub Actions + compose pull GitHub Actions + compose - меньше движущихся частей, Coolify опционально позже
Бэкапы pgBackRest + WAL в R2, restore-тест еженедельно pgBackRest + WAL в B2, restore-тест на ops консенсус, B2 (Object Lock дешевле) + Storage Box
BLOB-документы вынести в R2 вынести в B2, постепенно консенсус - выносим, поэтапно
Секреты sops + age sops + age консенсус
Мониторинг Netdata + Uptime Kuma + Grafana free + Sentry то же + Healthchecks.io консенсус
HA сейчас нет, быстрый DR нет, быстрый DR консенсус
Бюджет ~$82-84 ~$50-75 база / $130-150 профи ~$52-55 база

Оба консультанта независимо назвали одни и те же топ-риски: нет бэкапов → нет restore-тестов → прод смешан с Nextcloud → ручной деплой → нет мониторинга. Это и есть порядок работ.