Documentation

    Documentation

    Documentation

    Ring Platform Logo

    Завантаження документації...

    Підготовка контенту платформи Ring

    Ring Platform Logo

    Завантаження документації...

    Підготовка контенту платформи Ring

    Ring Platform Logo

    Завантаження документації...

    Підготовка контенту платформи Ring

    1. /
    2. /Режим k8s-postgres-fcm

    Обновлено 28 июн. 2026 г.6 мин прослушивания

    1. /
    2. /Режим k8s-postgres-fcm

    Обновлено 28 июн. 2026 г.6 мин прослушивания

    1. /
    2. /Режим k8s-postgres-fcm

    Обновлено 28 июн. 2026 г.6 мин прослушивания

    navigation.docs_sidebar.audience.founderHint

    Добро пожаловать в Ring Platform
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Архитектура
    Data Model
    Real Time
    Security
    Бекенд Сервисы
    Режим k8s-postgres-fcm
    Интеграция Firebase
    Функции
    Authentication
    Email AI-CRM
    Entities
    Opportunities
    Messaging
    Notifications
    Push-уведомления через FCM (Ring)
    Протокол Tunnel
    Web3 Кошелек
    Store
    Реферальные коды (Refcodes)
    Интеграция платежей
    PaymentConductor
    SubscriptionConductor
    Модуль Новостей - Цифровой Газетный Опыт
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Система локалей
    Безопасность и соответствие
    NFT Маркетплейс
    Система Стейкинга Токенов
    Паттерны Оптимизации Производительности
    Мобильный Опыт
    API-интерфейс
    Аутентификация
    Email AI-CRM API
    Сущности
    Opportunities
    Messaging
    Notifications
    Wallet
    Store
    Администрирование
    Кастомизация
    Настройка токеномики
    Branding
    Themes
    Web3
    Token launch jurisdictions
    Развёртывание
    Self-hosted развёртывание
    Vercel
    Docker
    Monitoring
    Оптимизация производительности
    Backup
    Разработка
    Локальная настройка
    Code Structure
    Компоненты документации
    Community tooling
    Ring MCP Server
    Генеративные изображения (ImageConductor)
    Автономная редакция (Grok)
    OSS vs enterprise
    Лучшие практики
    Workflow
    Code Style
    Производительность
    Testing
    Развёртывание
    Debugging
    Contributing
    Примеры
    Quick Start
    White Label
    Реальные Проекты
    Интеграции
    Ethereum-кошельки (Wagmi v3)

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и комплаенс
    ringdom.org — база LegioX
    Исходники — лицензия MIT (GitHub)

    navigation.docs_sidebar.audience.founderHint

    Добро пожаловать в Ring Platform
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Архитектура
    Data Model
    Real Time
    Security
    Бекенд Сервисы
    Режим k8s-postgres-fcm
    Интеграция Firebase
    Функции
    Authentication
    Email AI-CRM
    Entities
    Opportunities
    Messaging
    Notifications
    Push-уведомления через FCM (Ring)
    Протокол Tunnel
    Web3 Кошелек
    Store
    Реферальные коды (Refcodes)
    Интеграция платежей
    PaymentConductor
    SubscriptionConductor
    Модуль Новостей - Цифровой Газетный Опыт
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Система локалей
    Безопасность и соответствие
    NFT Маркетплейс
    Система Стейкинга Токенов
    Паттерны Оптимизации Производительности
    Мобильный Опыт
    API-интерфейс
    Аутентификация
    Email AI-CRM API
    Сущности
    Opportunities
    Messaging
    Notifications
    Wallet
    Store
    Администрирование
    Кастомизация
    Настройка токеномики
    Branding
    Themes
    Web3
    Token launch jurisdictions
    Развёртывание
    Self-hosted развёртывание
    Vercel
    Docker
    Monitoring
    Оптимизация производительности
    Backup
    Разработка
    Локальная настройка
    Code Structure
    Компоненты документации
    Community tooling
    Ring MCP Server
    Генеративные изображения (ImageConductor)
    Автономная редакция (Grok)
    OSS vs enterprise
    Лучшие практики
    Workflow
    Code Style
    Производительность
    Testing
    Развёртывание
    Debugging
    Contributing
    Примеры
    Quick Start
    White Label
    Реальные Проекты
    Интеграции
    Ethereum-кошельки (Wagmi v3)

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и комплаенс
    ringdom.org — база LegioX
    Исходники — лицензия MIT (GitHub)

    navigation.docs_sidebar.audience.founderHint

    Добро пожаловать в Ring Platform
    Краткий справочник
    С чего начать
    Предварительные требования
    Установка
    Первый успех
    Следующие шаги
    Архитектура
    Data Model
    Real Time
    Security
    Бекенд Сервисы
    Режим k8s-postgres-fcm
    Интеграция Firebase
    Функции
    Authentication
    Email AI-CRM
    Entities
    Opportunities
    Messaging
    Notifications
    Push-уведомления через FCM (Ring)
    Протокол Tunnel
    Web3 Кошелек
    Store
    Реферальные коды (Refcodes)
    Интеграция платежей
    PaymentConductor
    SubscriptionConductor
    Модуль Новостей - Цифровой Газетный Опыт
    Блоги участников
    Система Резервирования Имён Пользователей
    Научный редактор
    Система локалей
    Безопасность и соответствие
    NFT Маркетплейс
    Система Стейкинга Токенов
    Паттерны Оптимизации Производительности
    Мобильный Опыт
    API-интерфейс
    Аутентификация
    Email AI-CRM API
    Сущности
    Opportunities
    Messaging
    Notifications
    Wallet
    Store
    Администрирование
    Кастомизация
    Настройка токеномики
    Branding
    Themes
    Web3
    Token launch jurisdictions
    Развёртывание
    Self-hosted развёртывание
    Vercel
    Docker
    Monitoring
    Оптимизация производительности
    Backup
    Разработка
    Локальная настройка
    Code Structure
    Компоненты документации
    Community tooling
    Ring MCP Server
    Генеративные изображения (ImageConductor)
    Автономная редакция (Grok)
    OSS vs enterprise
    Лучшие практики
    Workflow
    Code Style
    Производительность
    Testing
    Развёртывание
    Debugging
    Contributing
    Примеры
    Quick Start
    White Label
    Реальные Проекты
    Интеграции
    Ethereum-кошельки (Wagmi v3)

    Быстрый вход (CTO · аудиторы · агенты)

    Приветствие — миссия и аудитории
    Краткий справочник
    С чего начать
    Архитектура и Auth.js
    Режимы бэкенда и БД (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Деплой (Docker · k8s)
    Безопасность и комплаенс
    ringdom.org — база LegioX
    Исходники — лицензия MIT (GitHub)
    Документация
    Бекенд Сервисы
    Документация
    Бекенд Сервисы
    Документация
    Бекенд Сервисы

    Режим k8s-postgres-fcm

    k8s-postgres-fcm — это рекомендованный бэкенд-режим для продакшна и локальной разработки. PostgreSQL на Kubernetes (или локально) обрабатывает все данные приложения, тогда как Firebase Admin SDK инициализируется исключительно для FCM push-сообщений и Apple Push. Никакой привязки к Firebase для данных приложения.

    Что даёт вам k8s-postgres-fcm

    • Полное владение данными приложения — хранятся в PostgreSQL 16 на вашей инфраструктуре. Никаких чтений или записей в Firestore.
    • Отсутствие привязки к Firebase для данных — миграция или смена провайдера требует только изменения строки подключения к базе данных, а не кода приложения.
    • Необязательные push-уведомления — FCM и Apple Push остаются доступными без предоставления доступа к вашей базе данных Firebase.
    • Интеграция Auth.js v5 — таблицы аутентификации (пользователи, учётные записи, сессии) хранятся в PostgreSQL вместе с бизнес-данными.
    • Поддержка PostGIS — возможность пространственных запросов для радиуса доставки магазина, местоположения сущностей, мест проведения мероприятий и функций недвижимости.
    • Нативный WebSocket транспорт — туннель использует нативный WSS через TUNNEL_HUB_MODE=k8s-postgres (или in-memory хаб для локальной разработки).

    Когда выбирать этот режим

    СценарийРекомендуемый режим
    Собственный продакшн на k3sk8s-postgres-fcm
    Локальная разработка с PostgreSQLk8s-postgres-fcm
    Облачный PostgreSQL (без K8s)supabase-fcm
    Быстрое прототипирование / Vercel Edgefirebase-full
    Push-уведомления нужнылюбой режим — FCM опционален во всех трёх

    Стоимостной профиль

    • PostgreSQL — работает на вашей собственной инфраструктуре (Kubernetes StatefulSet, bare metal или Docker). Без стоимости за запрос.
    • Firebase FCM — push-уведомления бесплатны на любом масштабе. Учётные данные проекта Firebase требуются только если вы включаете push.
    • Отсутствие расходов на Firestore — Firestore никогда не используется для данных приложения в этом режиме. Вызов getAdminDb() возвращает имитацию Firestore, которая никогда не подключается.

    Архитектура

    Ключевые точки принятия решений в коде:

    • shouldUseFirebaseForDatabase() возвращает false — getAdminDb() возвращает имитацию Firestore из build-mock.server.ts, которая никогда не подключается к Firebase.
    • shouldInitializeFirebaseFCM() возвращает true — Firebase Admin SDK инициализируется только для push-сообщений.
    • shouldInitializeApplePush() возвращает true — сервис Apple Push Notification Service доступен.
    • PostgreSQLAdapter реализует IDatabaseService и обрабатывает все CRUD, запросы, транзакции и операции подсчёта.

    Необходимые переменные окружения

    ПеременнаяОбязательноПо умолчаниюОписание
    DB_BACKEND_MODEДа—Должно быть k8s-postgres-fcm
    DB_HOSTДаlocalhostХост PostgreSQL
    DB_PORTНет5432Порт PostgreSQL

    Режим k8s-postgres-fcm

    k8s-postgres-fcm — это рекомендованный бэкенд-режим для продакшна и локальной разработки. PostgreSQL на Kubernetes (или локально) обрабатывает все данные приложения, тогда как Firebase Admin SDK инициализируется исключительно для FCM push-сообщений и Apple Push. Никакой привязки к Firebase для данных приложения.

    Что даёт вам k8s-postgres-fcm

    • Полное владение данными приложения — хранятся в PostgreSQL 16 на вашей инфраструктуре. Никаких чтений или записей в Firestore.
    • Отсутствие привязки к Firebase для данных — миграция или смена провайдера требует только изменения строки подключения к базе данных, а не кода приложения.
    • Необязательные push-уведомления — FCM и Apple Push остаются доступными без предоставления доступа к вашей базе данных Firebase.
    • Интеграция Auth.js v5 — таблицы аутентификации (пользователи, учётные записи, сессии) хранятся в PostgreSQL вместе с бизнес-данными.
    • Поддержка PostGIS — возможность пространственных запросов для радиуса доставки магазина, местоположения сущностей, мест проведения мероприятий и функций недвижимости.
    • Нативный WebSocket транспорт — туннель использует нативный WSS через TUNNEL_HUB_MODE=k8s-postgres (или in-memory хаб для локальной разработки).

    Когда выбирать этот режим

    СценарийРекомендуемый режим
    Собственный продакшн на k3sk8s-postgres-fcm
    Локальная разработка с PostgreSQLk8s-postgres-fcm
    Облачный PostgreSQL (без K8s)supabase-fcm
    Быстрое прототипирование / Vercel Edgefirebase-full
    Push-уведомления нужнылюбой режим — FCM опционален во всех трёх

    Стоимостной профиль

    • PostgreSQL — работает на вашей собственной инфраструктуре (Kubernetes StatefulSet, bare metal или Docker). Без стоимости за запрос.
    • Firebase FCM — push-уведомления бесплатны на любом масштабе. Учётные данные проекта Firebase требуются только если вы включаете push.
    • Отсутствие расходов на Firestore — Firestore никогда не используется для данных приложения в этом режиме. Вызов getAdminDb() возвращает имитацию Firestore, которая никогда не подключается.

    Архитектура

    Ключевые точки принятия решений в коде:

    • shouldUseFirebaseForDatabase() возвращает false — getAdminDb() возвращает имитацию Firestore из build-mock.server.ts, которая никогда не подключается к Firebase.
    • shouldInitializeFirebaseFCM() возвращает true — Firebase Admin SDK инициализируется только для push-сообщений.
    • shouldInitializeApplePush() возвращает true — сервис Apple Push Notification Service доступен.
    • PostgreSQLAdapter реализует IDatabaseService и обрабатывает все CRUD, запросы, транзакции и операции подсчёта.

    Необходимые переменные окружения

    ПеременнаяОбязательноПо умолчаниюОписание
    DB_BACKEND_MODEДа—Должно быть k8s-postgres-fcm
    DB_HOSTДаlocalhostХост PostgreSQL
    DB_PORTНет5432Порт PostgreSQL

    Режим k8s-postgres-fcm

    k8s-postgres-fcm — это рекомендованный бэкенд-режим для продакшна и локальной разработки. PostgreSQL на Kubernetes (или локально) обрабатывает все данные приложения, тогда как Firebase Admin SDK инициализируется исключительно для FCM push-сообщений и Apple Push. Никакой привязки к Firebase для данных приложения.

    Что даёт вам k8s-postgres-fcm

    • Полное владение данными приложения — хранятся в PostgreSQL 16 на вашей инфраструктуре. Никаких чтений или записей в Firestore.
    • Отсутствие привязки к Firebase для данных — миграция или смена провайдера требует только изменения строки подключения к базе данных, а не кода приложения.
    • Необязательные push-уведомления — FCM и Apple Push остаются доступными без предоставления доступа к вашей базе данных Firebase.
    • Интеграция Auth.js v5 — таблицы аутентификации (пользователи, учётные записи, сессии) хранятся в PostgreSQL вместе с бизнес-данными.
    • Поддержка PostGIS — возможность пространственных запросов для радиуса доставки магазина, местоположения сущностей, мест проведения мероприятий и функций недвижимости.
    • Нативный WebSocket транспорт — туннель использует нативный WSS через TUNNEL_HUB_MODE=k8s-postgres (или in-memory хаб для локальной разработки).

    Когда выбирать этот режим

    СценарийРекомендуемый режим
    Собственный продакшн на k3sk8s-postgres-fcm
    Локальная разработка с PostgreSQLk8s-postgres-fcm
    Облачный PostgreSQL (без K8s)supabase-fcm
    Быстрое прототипирование / Vercel Edgefirebase-full
    Push-уведомления нужнылюбой режим — FCM опционален во всех трёх

    Стоимостной профиль

    • PostgreSQL — работает на вашей собственной инфраструктуре (Kubernetes StatefulSet, bare metal или Docker). Без стоимости за запрос.
    • Firebase FCM — push-уведомления бесплатны на любом масштабе. Учётные данные проекта Firebase требуются только если вы включаете push.
    • Отсутствие расходов на Firestore — Firestore никогда не используется для данных приложения в этом режиме. Вызов getAdminDb() возвращает имитацию Firestore, которая никогда не подключается.

    Архитектура

    Ключевые точки принятия решений в коде:

    • shouldUseFirebaseForDatabase() возвращает false — getAdminDb() возвращает имитацию Firestore из build-mock.server.ts, которая никогда не подключается к Firebase.
    • shouldInitializeFirebaseFCM() возвращает true — Firebase Admin SDK инициализируется только для push-сообщений.
    • shouldInitializeApplePush() возвращает true — сервис Apple Push Notification Service доступен.
    • PostgreSQLAdapter реализует IDatabaseService и обрабатывает все CRUD, запросы, транзакции и операции подсчёта.

    Необходимые переменные окружения

    ПеременнаяОбязательноПо умолчаниюОписание
    DB_BACKEND_MODEДа—Должно быть k8s-postgres-fcm
    DB_HOSTДаlocalhostХост PostgreSQL
    DB_PORTНет5432Порт PostgreSQL
    DB_NAMEДаring_platformИмя базы данных
    DB_USERДаring_userПользователь базы данных
    DB_PASSWORDДаring_dev_passwordПароль базы данных
    DB_POOL_SIZEНет20Максимальный размер пула соединений
    DB_TIMEOUTНет30000Время ожидания соединения (мс)
    DB_RETRIESНет3Количество повторных попыток
    DB_SSLНетfalseВключить TLS для PostgreSQL
    DB_ENABLE_POSTGISНетfalseВключить расширения PostGIS

    Необязательные переменные окружения FCM / Firebase

    Требуются только если вам нужны push-уведомления. Без них платформа работает исключительно с PostgreSQL.

    Конфигурация подключения PostgreSQL

    PostgreSQLAdapter строит конфигурацию пула из переменных окружения. Источник: lib/database/adapters/PostgreSQLAdapter.ts:

    Адаптер использует гибридную JSONB-схему: большинство таблиц хранят бизнес-данные в столбце data типа JSONB вместе с общими столбцами id, created_at, updated_at. Таблицы с полностью нормализованными схемами (например, vendor_applications, vendor_profiles) перечисляют все столбцы в карте fieldMappings, поэтому конструктор запросов использует прямые ссылки на столбцы вместо data->>'field'.

    Адаптер поддерживает полный контракт DatabaseService:

    Локальная настройка

    1. Запустите PostgreSQL (два варианта):

      bash
      
      # Вариант A: Docker (рекомендуется)
      docker run -d --name ring-postgres-dev \
        -e POSTGRES_USER=ring_user \
        -e POSTGRES_PASSWORD=ring_password_2024 \
        -e POSTGRES_DB=ring_platform \
        -p 5432:5432 \
        postgres:16-alpine
      
      # Вариант B: Homebrew (macOS)
      brew install postgresql@16
      brew services start postgresql@16
      createdb ring_platform
    2. Создайте .env.local из шаблона и установите:

      bash
      
      DB_BACKEND_MODE=k8s-postgres-fcm
      DB_HOST=localhost
      DB_PORT=5432
      DB_NAME=ring_platform
      DB_USER=ring_user
      DB_PASSWORD=ring_password_2024
    3. Примените схему:

      bash
      
      psql -h localhost -U ring_user -d ring_platform -f data/schema.sql
    4. Запустите сервер разработки:

      bash
      
      npm run dev

      Платформа проверяет DB_BACKEND_MODE при запуске и логирует конфигурацию бэкенда. Вы должны увидеть Database: PostgreSQL в логах запуска.

    Туннельный хаб для функций реального времени:

    В локальной разработке туннель по умолчанию использует in-memory хаб. Для поведения, приближенного к продакшну, установите:

    Это сохраняет состояние туннеля в PostgreSQL вместо памяти процесса.

    Настройка продакшна на K8s

    1. Изоляция пространств имён

    Каждый клон ring получает собственное пространство имён: k8s/namespace.yaml

    2. StatefulSet PostgreSQL

    Манифест k8s/postgres.yaml развёртывает PostgreSQL 16 (образ: postgres:15) как Deployment с одной репликой и сервисом ClusterIP:

    • ConfigMap (postgres-config) — POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB
    • Init SQL — создаёт пользователя приложения (platform_org_user) и предоставляет привилегии
    • Расширения — uuid-ossp и btree_gin включены по умолчанию
    • Хранилище — том hostPath по пути /data/postgres-<clone-name>
    • Сервис — разрешается как postgres.<namespace>.svc.cluster.local

    3. Секреты и ConfigMap

    Секреты (k8s/secrets.yaml — Opaque, stringData):

    ConfigMap (k8s/secrets.yaml — секция ConfigMap):

    Важно: DB_PASSWORD должен быть в Secret, а не в ConfigMap. Развёртывание ссылается на него через secretKeyRef.

    4. Развёртывание приложения

    k8s/deployment.yaml — приложение Next.js 16 с:

    • Образ: ghcr.io/connectplatform/ring:v<version>-<clone>-amd64
    • 256Mi запрос / 1Gi лимит памяти
    • 200m / 1000m CPU
    • Liveness + readiness + startup пробы (/api/health)
    • Переменные окружения из ConfigMap (нечувствительные) и Secret (чувствительные)
    • Постоянный том для загруженных файлов (pvc-local-file-storage.yaml — 20Gi)
    • Pod anti-affinity для высокой доступности

    5. Ingress

    k8s/ingress.yaml — контроллер ingress nginx с:

    • Let's Encrypt TLS (cert-manager letsencrypt-prod)
    • Поддержка WebSocket (тайм-аут прокси 3600с, аннотация websocket-services)
    • Большой буфер прокси (32k — Next.js отправляет большие Link-заголовки для hreflang)
    • Ограничение скорости (100 RPS, 50 соединений)
    • Лимит размера тела 50MB

    6. Применение стека

    Настройка Docker

    Для локальных или продакшн-развёртываний на основе Docker docker-compose.yml поддерживает режим k8s-postgres-fcm. Убедитесь, что ваш .env содержит DB_BACKEND_MODE=k8s-postgres-fcm и переменные для подключения PostgreSQL:

    Примечание: Стандартный docker-compose.yml не включает сервис PostgreSQL. Вы должны либо:

    • Запустить PostgreSQL отдельно (собственная установка или docker run postgres:16-alpine)
    • Добавить сервис postgres в ваше переопределение (docker/docker-compose.dev.yml)

    Заметки о подключении FCM

    Этот режим использует Firebase Admin исключительно для push:

    1. Инициализация Admin SDK — приложение Firebase Admin создаётся, если присутствуют переменные окружения AUTH_FIREBASE_*. SDK требуется для генерации FCM-токенов и отправки push-сообщений.
    2. Имитация Firestore — getAdminDb() возвращает имитацию Firestore (никогда не подключается к Firebase). Это контролируется тем, что shouldUseFirebaseForDatabase() возвращает false.
    3. Имитация Auth — getAdminAuth() также возвращает имитацию. Auth.js v5 обрабатывает всю аутентификацию.
    4. Клиентский FCM — Service worker (public/firebase-messaging-sw.js) работает в браузере и загружает Firebase compat SDK с CDN. На него не влияет режим бэкенда — он всегда подключается к Firebase для push-подписки.
    5. FCM-токены — хранятся в таблице fcm_tokens PostgreSQL через Server Action upsertFcmToken.
    6. Без переменных окружения Firebase = без push — Если опустить все переменные AUTH_FIREBASE_* и NEXT_PUBLIC_FIREBASE_*, инициализация Firebase Admin полностью пропускается. PostgreSQL продолжает работать.

    Сравнение: k8s-postgres-fcm vs supabase-fcm

    Аспектk8s-postgres-fcmsupabase-fcm
    Хост PostgreSQLВаш K8s или локальныйОблако Supabase
    SSLОпционально (DB_SSL=false по умолчанию)Обязательно (DB_SSL=true)
    Пул соединенийDB_POOL_SIZE=20 по умолчаниюDB_POOL_SIZE=10 по умолчанию
    Учётные данныеDB_USER / DB_PASSWORDSUPABASE_URL / SUPABASE_SERVICE_KEY
    Цель развёртыванияK8s, Docker, bare metalПлатформа Supabase
    Манифесты K8sПолный набор в k8s/Не применимо
    Туннельный хабk8s-postgres или memorymemory
    PostGISDB_ENABLE_POSTGIS=trueТребует аддона Supabase PostGIS
    Вариант использованияПолный контроль инфраструктурыУправляемый облачный PostgreSQL

    Оба режима используют один и тот же класс PostgreSQLAdapter. Единственное отличие — кто хостит экземпляр PostgreSQL и как предоставляются параметры подключения.

    Связанная документация

    Backend modes and databases

    Database selection guide

    Environment variables

    Firebase integration

    Deployment guide

    Local setup

    bash
    
    # Выбор режима (ОБЯЗАТЕЛЬНО — платформа не запустится без него)
    DB_BACKEND_MODE=k8s-postgres-fcm
    
    # Подключение к PostgreSQL
    DB_HOST=localhost               # K8s: postgres.<namespace>.svc.cluster.local
    DB_PORT=5432
    DB_NAME=ring_platform
    DB_USER=ring_user
    DB_PASSWORD=ring_password_2024
    
    # Настройка пула соединений (необязательно, показано со значениями по умолчанию)
    DB_POOL_SIZE=20                 # Максимум соединений в пуле
    DB_TIMEOUT=30000                # Время ожидания соединения в мс
    DB_RETRIES=3                    # Попытки повтора при сбое
    DB_SSL=false                    # Установите true для продакшна и Supabase
    
    # PostGIS (необязательно)
    DB_ENABLE_POSTGIS=false         # Включить пространственные расширения
    text
    
    ┌─────────────────────────────────────────────────┐
    │                Next.js 16 App                     │
    │                                                   │
    │  ┌──────────────────────┐  ┌──────────────────┐  │
    │  │  PostgreSQLAdapter   │  │  Firebase Admin   │  │
    │  │  (all CRUD / query)  │  │  (FCM + Apple     │  │
    │  │                      │  │   Push only)      │  │
    │  │  • Auth.js tables    │  │                   │  │
    │  │  • Entities          │  │  • getAdminDb()   │  │
    │  │  • Store products    │  │    → mock (never  │  │
    │  │  • Conversations     │  │      connects)    │  │
    │  │  • FCM tokens        │  │  • getAdminAuth() │  │
    │  │  • All business data │  │    → mock         │  │
    │  └────────┬─────────────┘  └────────┬─────────┘  │
    │           │                         │            │
    └───────────┼─────────────────────────┼────────────┘
                │                         │
                ▼                         ▼
       ┌─────────────────┐     ┌──────────────────┐
       │  PostgreSQL 16   │     │  Firebase FCM    │
       │  + PostGIS       │     │  (push only)     │
       │  StatefulSet     │     └──────────────────┘
       │  (k8s or local)  │
       └─────────────────┘
    bash
    
    # Firebase Admin SDK (серверный) — требуется для FCM
    AUTH_FIREBASE_PROJECT_ID=your_firebase_project_id
    AUTH_FIREBASE_CLIENT_EMAIL=your_firebase_client_email
    AUTH_FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
    
    # Firebase client SDK (браузерный) — для регистрации push через service worker
    NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
    NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
    NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_firebase_project_id
    NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
    NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id
    NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
    NEXT_PUBLIC_FIREBASE_VAPID_KEY=your_vapid_key
    typescript
    
    const poolConfig = {
      host: config.connection.host || 'localhost',
      port: config.connection.port || 5432,
      database: config.connection.database || 'ring_platform',
      user: config.connection.username || 'ring_user',
      password: config.connection.password || 'ring_dev_password',
      max: config.options.poolSize || 20,
      idleTimeoutMillis: config.options.timeout || 30000,
      connectionTimeoutMillis: config.options.timeout || 2000,
    }
    typescript
    
    // Операции с отдельными документами
    await db.findById('users', userId)
    await db.create('users', { name: 'Алиса', email: 'alice@example.com' })
    await db.update('users', userId, { name: 'Боб' })
    await db.delete('users', userId)
    
    // Запросы с фильтрами, сортировкой, пагинацией
    await db.query({
      collection: 'entities',
      filters: [{ field: 'status', operator: 'eq', value: 'active' }],
      orderBy: [{ field: 'createdAt', direction: 'desc' }],
      pagination: { limit: 20, offset: 0 },
    })
    
    // Транзакции
    await db.transaction(async (txn) => {
      const order = await txn.create('orders', { total: 100 })
      await txn.update('stock', productId, { quantity: 5 })
    })
    bash
    
    TUNNEL_HUB_MODE=k8s-postgres
    yaml
    
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ring-platform-org
      labels:
        app.kubernetes.io/name: ring-platform-org
        app.kubernetes.io/part-of: ringdom
    yaml
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: ring-platform-org-secrets
    type: Opaque
    stringData:
      DB_PASSWORD: <value>
      AUTH_FIREBASE_PROJECT_ID: <value>
      AUTH_FIREBASE_CLIENT_EMAIL: <value>
      AUTH_FIREBASE_PRIVATE_KEY: |
        -----BEGIN PRIVATE KEY-----
        ...
        -----END PRIVATE KEY-----
    yaml
    
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ring-platform-org-config
    data:
      DB_BACKEND_MODE: k8s-postgres-fcm
      DB_HOST: postgres.ring-platform-org.svc.cluster.local
      DB_PORT: "5432"
      DB_NAME: ring_platform
      DB_USER: ring_user
      DB_POOL_SIZE: "20"
      DB_TIMEOUT: "30000"
      DB_RETRIES: "3"
      DB_SSL: "false"
      NEXT_PUBLIC_FIREBASE_PROJECT_ID: <value>
    bash
    
    kubectl apply -f k8s/namespace.yaml
    kubectl apply -f k8s/postgres.yaml
    kubectl apply -f k8s/secrets.yaml
    kubectl apply -f k8s/deployment.yaml
    kubectl apply -f k8s/service.yaml
    kubectl apply -f k8s/ingress.yaml
    kubectl apply -f k8s/pvc-local-file-storage.yaml
    bash
    
    docker compose up -d
    DB_NAMEДаring_platformИмя базы данных
    DB_USERДаring_userПользователь базы данных
    DB_PASSWORDДаring_dev_passwordПароль базы данных
    DB_POOL_SIZEНет20Максимальный размер пула соединений
    DB_TIMEOUTНет30000Время ожидания соединения (мс)
    DB_RETRIESНет3Количество повторных попыток
    DB_SSLНетfalseВключить TLS для PostgreSQL
    DB_ENABLE_POSTGISНетfalseВключить расширения PostGIS

    Необязательные переменные окружения FCM / Firebase

    Требуются только если вам нужны push-уведомления. Без них платформа работает исключительно с PostgreSQL.

    Конфигурация подключения PostgreSQL

    PostgreSQLAdapter строит конфигурацию пула из переменных окружения. Источник: lib/database/adapters/PostgreSQLAdapter.ts:

    Адаптер использует гибридную JSONB-схему: большинство таблиц хранят бизнес-данные в столбце data типа JSONB вместе с общими столбцами id, created_at, updated_at. Таблицы с полностью нормализованными схемами (например, vendor_applications, vendor_profiles) перечисляют все столбцы в карте fieldMappings, поэтому конструктор запросов использует прямые ссылки на столбцы вместо data->>'field'.

    Адаптер поддерживает полный контракт DatabaseService:

    Локальная настройка

    1. Запустите PostgreSQL (два варианта):

      bash
      
      # Вариант A: Docker (рекомендуется)
      docker run -d --name ring-postgres-dev \
        -e POSTGRES_USER=ring_user \
        -e POSTGRES_PASSWORD=ring_password_2024 \
        -e POSTGRES_DB=ring_platform \
        -p 5432:5432 \
        postgres:16-alpine
      
      # Вариант B: Homebrew (macOS)
      brew install postgresql@16
      brew services start postgresql@16
      createdb ring_platform
    2. Создайте .env.local из шаблона и установите:

      bash
      
      DB_BACKEND_MODE=k8s-postgres-fcm
      DB_HOST=localhost
      DB_PORT=5432
      DB_NAME=ring_platform
      DB_USER=ring_user
      DB_PASSWORD=ring_password_2024
    3. Примените схему:

      bash
      
      psql -h localhost -U ring_user -d ring_platform -f data/schema.sql
    4. Запустите сервер разработки:

      bash
      
      npm run dev

      Платформа проверяет DB_BACKEND_MODE при запуске и логирует конфигурацию бэкенда. Вы должны увидеть Database: PostgreSQL в логах запуска.

    Туннельный хаб для функций реального времени:

    В локальной разработке туннель по умолчанию использует in-memory хаб. Для поведения, приближенного к продакшну, установите:

    Это сохраняет состояние туннеля в PostgreSQL вместо памяти процесса.

    Настройка продакшна на K8s

    1. Изоляция пространств имён

    Каждый клон ring получает собственное пространство имён: k8s/namespace.yaml

    2. StatefulSet PostgreSQL

    Манифест k8s/postgres.yaml развёртывает PostgreSQL 16 (образ: postgres:15) как Deployment с одной репликой и сервисом ClusterIP:

    • ConfigMap (postgres-config) — POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB
    • Init SQL — создаёт пользователя приложения (platform_org_user) и предоставляет привилегии
    • Расширения — uuid-ossp и btree_gin включены по умолчанию
    • Хранилище — том hostPath по пути /data/postgres-<clone-name>
    • Сервис — разрешается как postgres.<namespace>.svc.cluster.local

    3. Секреты и ConfigMap

    Секреты (k8s/secrets.yaml — Opaque, stringData):

    ConfigMap (k8s/secrets.yaml — секция ConfigMap):

    Важно: DB_PASSWORD должен быть в Secret, а не в ConfigMap. Развёртывание ссылается на него через secretKeyRef.

    4. Развёртывание приложения

    k8s/deployment.yaml — приложение Next.js 16 с:

    • Образ: ghcr.io/connectplatform/ring:v<version>-<clone>-amd64
    • 256Mi запрос / 1Gi лимит памяти
    • 200m / 1000m CPU
    • Liveness + readiness + startup пробы (/api/health)
    • Переменные окружения из ConfigMap (нечувствительные) и Secret (чувствительные)
    • Постоянный том для загруженных файлов (pvc-local-file-storage.yaml — 20Gi)
    • Pod anti-affinity для высокой доступности

    5. Ingress

    k8s/ingress.yaml — контроллер ingress nginx с:

    • Let's Encrypt TLS (cert-manager letsencrypt-prod)
    • Поддержка WebSocket (тайм-аут прокси 3600с, аннотация websocket-services)
    • Большой буфер прокси (32k — Next.js отправляет большие Link-заголовки для hreflang)
    • Ограничение скорости (100 RPS, 50 соединений)
    • Лимит размера тела 50MB

    6. Применение стека

    Настройка Docker

    Для локальных или продакшн-развёртываний на основе Docker docker-compose.yml поддерживает режим k8s-postgres-fcm. Убедитесь, что ваш .env содержит DB_BACKEND_MODE=k8s-postgres-fcm и переменные для подключения PostgreSQL:

    Примечание: Стандартный docker-compose.yml не включает сервис PostgreSQL. Вы должны либо:

    • Запустить PostgreSQL отдельно (собственная установка или docker run postgres:16-alpine)
    • Добавить сервис postgres в ваше переопределение (docker/docker-compose.dev.yml)

    Заметки о подключении FCM

    Этот режим использует Firebase Admin исключительно для push:

    1. Инициализация Admin SDK — приложение Firebase Admin создаётся, если присутствуют переменные окружения AUTH_FIREBASE_*. SDK требуется для генерации FCM-токенов и отправки push-сообщений.
    2. Имитация Firestore — getAdminDb() возвращает имитацию Firestore (никогда не подключается к Firebase). Это контролируется тем, что shouldUseFirebaseForDatabase() возвращает false.
    3. Имитация Auth — getAdminAuth() также возвращает имитацию. Auth.js v5 обрабатывает всю аутентификацию.
    4. Клиентский FCM — Service worker (public/firebase-messaging-sw.js) работает в браузере и загружает Firebase compat SDK с CDN. На него не влияет режим бэкенда — он всегда подключается к Firebase для push-подписки.
    5. FCM-токены — хранятся в таблице fcm_tokens PostgreSQL через Server Action upsertFcmToken.
    6. Без переменных окружения Firebase = без push — Если опустить все переменные AUTH_FIREBASE_* и NEXT_PUBLIC_FIREBASE_*, инициализация Firebase Admin полностью пропускается. PostgreSQL продолжает работать.

    Сравнение: k8s-postgres-fcm vs supabase-fcm

    Аспектk8s-postgres-fcmsupabase-fcm
    Хост PostgreSQLВаш K8s или локальныйОблако Supabase
    SSLОпционально (DB_SSL=false по умолчанию)Обязательно (DB_SSL=true)
    Пул соединенийDB_POOL_SIZE=20 по умолчаниюDB_POOL_SIZE=10 по умолчанию
    Учётные данныеDB_USER / DB_PASSWORDSUPABASE_URL / SUPABASE_SERVICE_KEY
    Цель развёртыванияK8s, Docker, bare metalПлатформа Supabase
    Манифесты K8sПолный набор в k8s/Не применимо
    Туннельный хабk8s-postgres или memorymemory
    PostGISDB_ENABLE_POSTGIS=trueТребует аддона Supabase PostGIS
    Вариант использованияПолный контроль инфраструктурыУправляемый облачный PostgreSQL

    Оба режима используют один и тот же класс PostgreSQLAdapter. Единственное отличие — кто хостит экземпляр PostgreSQL и как предоставляются параметры подключения.

    Связанная документация

    Backend modes and databases

    Database selection guide

    Environment variables

    Firebase integration

    Deployment guide

    Local setup

    bash
    
    # Выбор режима (ОБЯЗАТЕЛЬНО — платформа не запустится без него)
    DB_BACKEND_MODE=k8s-postgres-fcm
    
    # Подключение к PostgreSQL
    DB_HOST=localhost               # K8s: postgres.<namespace>.svc.cluster.local
    DB_PORT=5432
    DB_NAME=ring_platform
    DB_USER=ring_user
    DB_PASSWORD=ring_password_2024
    
    # Настройка пула соединений (необязательно, показано со значениями по умолчанию)
    DB_POOL_SIZE=20                 # Максимум соединений в пуле
    DB_TIMEOUT=30000                # Время ожидания соединения в мс
    DB_RETRIES=3                    # Попытки повтора при сбое
    DB_SSL=false                    # Установите true для продакшна и Supabase
    
    # PostGIS (необязательно)
    DB_ENABLE_POSTGIS=false         # Включить пространственные расширения
    text
    
    ┌─────────────────────────────────────────────────┐
    │                Next.js 16 App                     │
    │                                                   │
    │  ┌──────────────────────┐  ┌──────────────────┐  │
    │  │  PostgreSQLAdapter   │  │  Firebase Admin   │  │
    │  │  (all CRUD / query)  │  │  (FCM + Apple     │  │
    │  │                      │  │   Push only)      │  │
    │  │  • Auth.js tables    │  │                   │  │
    │  │  • Entities          │  │  • getAdminDb()   │  │
    │  │  • Store products    │  │    → mock (never  │  │
    │  │  • Conversations     │  │      connects)    │  │
    │  │  • FCM tokens        │  │  • getAdminAuth() │  │
    │  │  • All business data │  │    → mock         │  │
    │  └────────┬─────────────┘  └────────┬─────────┘  │
    │           │                         │            │
    └───────────┼─────────────────────────┼────────────┘
                │                         │
                ▼                         ▼
       ┌─────────────────┐     ┌──────────────────┐
       │  PostgreSQL 16   │     │  Firebase FCM    │
       │  + PostGIS       │     │  (push only)     │
       │  StatefulSet     │     └──────────────────┘
       │  (k8s or local)  │
       └─────────────────┘
    bash
    
    # Firebase Admin SDK (серверный) — требуется для FCM
    AUTH_FIREBASE_PROJECT_ID=your_firebase_project_id
    AUTH_FIREBASE_CLIENT_EMAIL=your_firebase_client_email
    AUTH_FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
    
    # Firebase client SDK (браузерный) — для регистрации push через service worker
    NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
    NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
    NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_firebase_project_id
    NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
    NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id
    NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
    NEXT_PUBLIC_FIREBASE_VAPID_KEY=your_vapid_key
    typescript
    
    const poolConfig = {
      host: config.connection.host || 'localhost',
      port: config.connection.port || 5432,
      database: config.connection.database || 'ring_platform',
      user: config.connection.username || 'ring_user',
      password: config.connection.password || 'ring_dev_password',
      max: config.options.poolSize || 20,
      idleTimeoutMillis: config.options.timeout || 30000,
      connectionTimeoutMillis: config.options.timeout || 2000,
    }
    typescript
    
    // Операции с отдельными документами
    await db.findById('users', userId)
    await db.create('users', { name: 'Алиса', email: 'alice@example.com' })
    await db.update('users', userId, { name: 'Боб' })
    await db.delete('users', userId)
    
    // Запросы с фильтрами, сортировкой, пагинацией
    await db.query({
      collection: 'entities',
      filters: [{ field: 'status', operator: 'eq', value: 'active' }],
      orderBy: [{ field: 'createdAt', direction: 'desc' }],
      pagination: { limit: 20, offset: 0 },
    })
    
    // Транзакции
    await db.transaction(async (txn) => {
      const order = await txn.create('orders', { total: 100 })
      await txn.update('stock', productId, { quantity: 5 })
    })
    bash
    
    TUNNEL_HUB_MODE=k8s-postgres
    yaml
    
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ring-platform-org
      labels:
        app.kubernetes.io/name: ring-platform-org
        app.kubernetes.io/part-of: ringdom
    yaml
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: ring-platform-org-secrets
    type: Opaque
    stringData:
      DB_PASSWORD: <value>
      AUTH_FIREBASE_PROJECT_ID: <value>
      AUTH_FIREBASE_CLIENT_EMAIL: <value>
      AUTH_FIREBASE_PRIVATE_KEY: |
        -----BEGIN PRIVATE KEY-----
        ...
        -----END PRIVATE KEY-----
    yaml
    
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ring-platform-org-config
    data:
      DB_BACKEND_MODE: k8s-postgres-fcm
      DB_HOST: postgres.ring-platform-org.svc.cluster.local
      DB_PORT: "5432"
      DB_NAME: ring_platform
      DB_USER: ring_user
      DB_POOL_SIZE: "20"
      DB_TIMEOUT: "30000"
      DB_RETRIES: "3"
      DB_SSL: "false"
      NEXT_PUBLIC_FIREBASE_PROJECT_ID: <value>
    bash
    
    kubectl apply -f k8s/namespace.yaml
    kubectl apply -f k8s/postgres.yaml
    kubectl apply -f k8s/secrets.yaml
    kubectl apply -f k8s/deployment.yaml
    kubectl apply -f k8s/service.yaml
    kubectl apply -f k8s/ingress.yaml
    kubectl apply -f k8s/pvc-local-file-storage.yaml
    bash
    
    docker compose up -d
    DB_NAMEДаring_platformИмя базы данных
    DB_USERДаring_userПользователь базы данных
    DB_PASSWORDДаring_dev_passwordПароль базы данных
    DB_POOL_SIZEНет20Максимальный размер пула соединений
    DB_TIMEOUTНет30000Время ожидания соединения (мс)
    DB_RETRIESНет3Количество повторных попыток
    DB_SSLНетfalseВключить TLS для PostgreSQL
    DB_ENABLE_POSTGISНетfalseВключить расширения PostGIS

    Необязательные переменные окружения FCM / Firebase

    Требуются только если вам нужны push-уведомления. Без них платформа работает исключительно с PostgreSQL.

    Конфигурация подключения PostgreSQL

    PostgreSQLAdapter строит конфигурацию пула из переменных окружения. Источник: lib/database/adapters/PostgreSQLAdapter.ts:

    Адаптер использует гибридную JSONB-схему: большинство таблиц хранят бизнес-данные в столбце data типа JSONB вместе с общими столбцами id, created_at, updated_at. Таблицы с полностью нормализованными схемами (например, vendor_applications, vendor_profiles) перечисляют все столбцы в карте fieldMappings, поэтому конструктор запросов использует прямые ссылки на столбцы вместо data->>'field'.

    Адаптер поддерживает полный контракт DatabaseService:

    Локальная настройка

    1. Запустите PostgreSQL (два варианта):

      bash
      
      # Вариант A: Docker (рекомендуется)
      docker run -d --name ring-postgres-dev \
        -e POSTGRES_USER=ring_user \
        -e POSTGRES_PASSWORD=ring_password_2024 \
        -e POSTGRES_DB=ring_platform \
        -p 5432:5432 \
        postgres:16-alpine
      
      # Вариант B: Homebrew (macOS)
      brew install postgresql@16
      brew services start postgresql@16
      createdb ring_platform
    2. Создайте .env.local из шаблона и установите:

      bash
      
      DB_BACKEND_MODE=k8s-postgres-fcm
      DB_HOST=localhost
      DB_PORT=5432
      DB_NAME=ring_platform
      DB_USER=ring_user
      DB_PASSWORD=ring_password_2024
    3. Примените схему:

      bash
      
      psql -h localhost -U ring_user -d ring_platform -f data/schema.sql
    4. Запустите сервер разработки:

      bash
      
      npm run dev

      Платформа проверяет DB_BACKEND_MODE при запуске и логирует конфигурацию бэкенда. Вы должны увидеть Database: PostgreSQL в логах запуска.

    Туннельный хаб для функций реального времени:

    В локальной разработке туннель по умолчанию использует in-memory хаб. Для поведения, приближенного к продакшну, установите:

    Это сохраняет состояние туннеля в PostgreSQL вместо памяти процесса.

    Настройка продакшна на K8s

    1. Изоляция пространств имён

    Каждый клон ring получает собственное пространство имён: k8s/namespace.yaml

    2. StatefulSet PostgreSQL

    Манифест k8s/postgres.yaml развёртывает PostgreSQL 16 (образ: postgres:15) как Deployment с одной репликой и сервисом ClusterIP:

    • ConfigMap (postgres-config) — POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB
    • Init SQL — создаёт пользователя приложения (platform_org_user) и предоставляет привилегии
    • Расширения — uuid-ossp и btree_gin включены по умолчанию
    • Хранилище — том hostPath по пути /data/postgres-<clone-name>
    • Сервис — разрешается как postgres.<namespace>.svc.cluster.local

    3. Секреты и ConfigMap

    Секреты (k8s/secrets.yaml — Opaque, stringData):

    ConfigMap (k8s/secrets.yaml — секция ConfigMap):

    Важно: DB_PASSWORD должен быть в Secret, а не в ConfigMap. Развёртывание ссылается на него через secretKeyRef.

    4. Развёртывание приложения

    k8s/deployment.yaml — приложение Next.js 16 с:

    • Образ: ghcr.io/connectplatform/ring:v<version>-<clone>-amd64
    • 256Mi запрос / 1Gi лимит памяти
    • 200m / 1000m CPU
    • Liveness + readiness + startup пробы (/api/health)
    • Переменные окружения из ConfigMap (нечувствительные) и Secret (чувствительные)
    • Постоянный том для загруженных файлов (pvc-local-file-storage.yaml — 20Gi)
    • Pod anti-affinity для высокой доступности

    5. Ingress

    k8s/ingress.yaml — контроллер ingress nginx с:

    • Let's Encrypt TLS (cert-manager letsencrypt-prod)
    • Поддержка WebSocket (тайм-аут прокси 3600с, аннотация websocket-services)
    • Большой буфер прокси (32k — Next.js отправляет большие Link-заголовки для hreflang)
    • Ограничение скорости (100 RPS, 50 соединений)
    • Лимит размера тела 50MB

    6. Применение стека

    Настройка Docker

    Для локальных или продакшн-развёртываний на основе Docker docker-compose.yml поддерживает режим k8s-postgres-fcm. Убедитесь, что ваш .env содержит DB_BACKEND_MODE=k8s-postgres-fcm и переменные для подключения PostgreSQL:

    Примечание: Стандартный docker-compose.yml не включает сервис PostgreSQL. Вы должны либо:

    • Запустить PostgreSQL отдельно (собственная установка или docker run postgres:16-alpine)
    • Добавить сервис postgres в ваше переопределение (docker/docker-compose.dev.yml)

    Заметки о подключении FCM

    Этот режим использует Firebase Admin исключительно для push:

    1. Инициализация Admin SDK — приложение Firebase Admin создаётся, если присутствуют переменные окружения AUTH_FIREBASE_*. SDK требуется для генерации FCM-токенов и отправки push-сообщений.
    2. Имитация Firestore — getAdminDb() возвращает имитацию Firestore (никогда не подключается к Firebase). Это контролируется тем, что shouldUseFirebaseForDatabase() возвращает false.
    3. Имитация Auth — getAdminAuth() также возвращает имитацию. Auth.js v5 обрабатывает всю аутентификацию.
    4. Клиентский FCM — Service worker (public/firebase-messaging-sw.js) работает в браузере и загружает Firebase compat SDK с CDN. На него не влияет режим бэкенда — он всегда подключается к Firebase для push-подписки.
    5. FCM-токены — хранятся в таблице fcm_tokens PostgreSQL через Server Action upsertFcmToken.
    6. Без переменных окружения Firebase = без push — Если опустить все переменные AUTH_FIREBASE_* и NEXT_PUBLIC_FIREBASE_*, инициализация Firebase Admin полностью пропускается. PostgreSQL продолжает работать.

    Сравнение: k8s-postgres-fcm vs supabase-fcm

    Аспектk8s-postgres-fcmsupabase-fcm
    Хост PostgreSQLВаш K8s или локальныйОблако Supabase
    SSLОпционально (DB_SSL=false по умолчанию)Обязательно (DB_SSL=true)
    Пул соединенийDB_POOL_SIZE=20 по умолчаниюDB_POOL_SIZE=10 по умолчанию
    Учётные данныеDB_USER / DB_PASSWORDSUPABASE_URL / SUPABASE_SERVICE_KEY
    Цель развёртыванияK8s, Docker, bare metalПлатформа Supabase
    Манифесты K8sПолный набор в k8s/Не применимо
    Туннельный хабk8s-postgres или memorymemory
    PostGISDB_ENABLE_POSTGIS=trueТребует аддона Supabase PostGIS
    Вариант использованияПолный контроль инфраструктурыУправляемый облачный PostgreSQL

    Оба режима используют один и тот же класс PostgreSQLAdapter. Единственное отличие — кто хостит экземпляр PostgreSQL и как предоставляются параметры подключения.

    Связанная документация

    Backend modes and databases

    Database selection guide

    Environment variables

    Firebase integration

    Deployment guide

    Local setup

    bash
    
    # Выбор режима (ОБЯЗАТЕЛЬНО — платформа не запустится без него)
    DB_BACKEND_MODE=k8s-postgres-fcm
    
    # Подключение к PostgreSQL
    DB_HOST=localhost               # K8s: postgres.<namespace>.svc.cluster.local
    DB_PORT=5432
    DB_NAME=ring_platform
    DB_USER=ring_user
    DB_PASSWORD=ring_password_2024
    
    # Настройка пула соединений (необязательно, показано со значениями по умолчанию)
    DB_POOL_SIZE=20                 # Максимум соединений в пуле
    DB_TIMEOUT=30000                # Время ожидания соединения в мс
    DB_RETRIES=3                    # Попытки повтора при сбое
    DB_SSL=false                    # Установите true для продакшна и Supabase
    
    # PostGIS (необязательно)
    DB_ENABLE_POSTGIS=false         # Включить пространственные расширения
    text
    
    ┌─────────────────────────────────────────────────┐
    │                Next.js 16 App                     │
    │                                                   │
    │  ┌──────────────────────┐  ┌──────────────────┐  │
    │  │  PostgreSQLAdapter   │  │  Firebase Admin   │  │
    │  │  (all CRUD / query)  │  │  (FCM + Apple     │  │
    │  │                      │  │   Push only)      │  │
    │  │  • Auth.js tables    │  │                   │  │
    │  │  • Entities          │  │  • getAdminDb()   │  │
    │  │  • Store products    │  │    → mock (never  │  │
    │  │  • Conversations     │  │      connects)    │  │
    │  │  • FCM tokens        │  │  • getAdminAuth() │  │
    │  │  • All business data │  │    → mock         │  │
    │  └────────┬─────────────┘  └────────┬─────────┘  │
    │           │                         │            │
    └───────────┼─────────────────────────┼────────────┘
                │                         │
                ▼                         ▼
       ┌─────────────────┐     ┌──────────────────┐
       │  PostgreSQL 16   │     │  Firebase FCM    │
       │  + PostGIS       │     │  (push only)     │
       │  StatefulSet     │     └──────────────────┘
       │  (k8s or local)  │
       └─────────────────┘
    bash
    
    # Firebase Admin SDK (серверный) — требуется для FCM
    AUTH_FIREBASE_PROJECT_ID=your_firebase_project_id
    AUTH_FIREBASE_CLIENT_EMAIL=your_firebase_client_email
    AUTH_FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
    
    # Firebase client SDK (браузерный) — для регистрации push через service worker
    NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
    NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_auth_domain
    NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_firebase_project_id
    NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_storage_bucket
    NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id
    NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
    NEXT_PUBLIC_FIREBASE_VAPID_KEY=your_vapid_key
    typescript
    
    const poolConfig = {
      host: config.connection.host || 'localhost',
      port: config.connection.port || 5432,
      database: config.connection.database || 'ring_platform',
      user: config.connection.username || 'ring_user',
      password: config.connection.password || 'ring_dev_password',
      max: config.options.poolSize || 20,
      idleTimeoutMillis: config.options.timeout || 30000,
      connectionTimeoutMillis: config.options.timeout || 2000,
    }
    typescript
    
    // Операции с отдельными документами
    await db.findById('users', userId)
    await db.create('users', { name: 'Алиса', email: 'alice@example.com' })
    await db.update('users', userId, { name: 'Боб' })
    await db.delete('users', userId)
    
    // Запросы с фильтрами, сортировкой, пагинацией
    await db.query({
      collection: 'entities',
      filters: [{ field: 'status', operator: 'eq', value: 'active' }],
      orderBy: [{ field: 'createdAt', direction: 'desc' }],
      pagination: { limit: 20, offset: 0 },
    })
    
    // Транзакции
    await db.transaction(async (txn) => {
      const order = await txn.create('orders', { total: 100 })
      await txn.update('stock', productId, { quantity: 5 })
    })
    bash
    
    TUNNEL_HUB_MODE=k8s-postgres
    yaml
    
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ring-platform-org
      labels:
        app.kubernetes.io/name: ring-platform-org
        app.kubernetes.io/part-of: ringdom
    yaml
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: ring-platform-org-secrets
    type: Opaque
    stringData:
      DB_PASSWORD: <value>
      AUTH_FIREBASE_PROJECT_ID: <value>
      AUTH_FIREBASE_CLIENT_EMAIL: <value>
      AUTH_FIREBASE_PRIVATE_KEY: |
        -----BEGIN PRIVATE KEY-----
        ...
        -----END PRIVATE KEY-----
    yaml
    
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ring-platform-org-config
    data:
      DB_BACKEND_MODE: k8s-postgres-fcm
      DB_HOST: postgres.ring-platform-org.svc.cluster.local
      DB_PORT: "5432"
      DB_NAME: ring_platform
      DB_USER: ring_user
      DB_POOL_SIZE: "20"
      DB_TIMEOUT: "30000"
      DB_RETRIES: "3"
      DB_SSL: "false"
      NEXT_PUBLIC_FIREBASE_PROJECT_ID: <value>
    bash
    
    kubectl apply -f k8s/namespace.yaml
    kubectl apply -f k8s/postgres.yaml
    kubectl apply -f k8s/secrets.yaml
    kubectl apply -f k8s/deployment.yaml
    kubectl apply -f k8s/service.yaml
    kubectl apply -f k8s/ingress.yaml
    kubectl apply -f k8s/pvc-local-file-storage.yaml
    bash
    
    docker compose up -d