Краткий вывод: Для стабильного развертывания self-hosted Supabase на VPS в Docker Compose требуется KVM-нода минимум с 2 vCPU, 4 ГБ RAM (от 8 ГБ под Production-нагрузку) и NVMe-диском с высоким запасом IOPS для исключения блокировок на операциях WAL-журналирования PostgreSQL. Архитектура решения требует Reverse Proxy с поддержкой TLS 1.3, постоянного сквозного проксирования WebSocket (WSS) для сервиса Realtime и прямого выделенного IPv4 без NAT для валидации внешних OAuth-сессий в сервисе Auth (GoTrue).
Содержание
- Аппаратные требования и сайзинг KVM-сервера под стек Supabase
- Архитектура Self-Hosted Supabase: разбор ключевых микросервисов
- Подготовка операционной системы и настройка окружения Docker
- Пошаговое развертывание Supabase через официальный Docker Compose
- Генерация криптографических секретов и харденинг .env
- Публикация сервиса: Nginx Reverse Proxy, Let's Encrypt SSL и WebSockets
- Тюнинг производительности PostgreSQL под высокие нагрузки
- Регламент Disaster Recovery: бэкапы PostgreSQL и план аварийного восстановления
- Экономика и архитектура: Supabase Cloud vs Firebase vs Self-Hosted KVM VPS
- Часто задаваемые вопросы (FAQ)
Аппаратные требования и сайзинг KVM-сервера под стек Supabase
Развертывание стека Supabase на VPS представляет собой запуск распределенной микросервисной системы из более чем десяти связанных Docker-контейнеров: реляционного ядра PostgreSQL 15/16 (с расширениями pgvector, pg_stat_statements, pgjwt), авторизационного шлюза GoTrue, REST-интерфейса PostgREST, брокера Realtime на базе Elixir/BEAM, хранилища Storage API, кэширующего шлюза Kong и веб-интерфейса Studio. Для изоляции стека необходима аппаратная виртуализация KVM, так как в контейнерных средах OpenVZ/LXC заблокирован прямой доступ к подсистеме cgroups v2, ограничена модификация параметров виртуальной памяти ядра (vm.overcommit_memory) и отсутствует гарантия физического выделения вычислительных ресурсов.
Вычислительная подсистема и показатель CPU Steal Time
Процессорная мощность напрямую определяет пропускную способность транзакционного ядра базы данных и стабильность работы диспетчера очередей Elixir BEAM. При обработке сотен входящих HTTP-запросов и WebSocket-соединений критически важна изоляция vCPU.
Главный индикатор переподписки вычислительных узлов со стороны хостера — CPU Steal Time (%st). Контролировать его значение на работающем инстансе необходимо через vmstat 1 или top:
vmstat 1 5 | awk '{print "US:", $13, "SY:", $14, "ID:", $15, "WA:", $16, "ST (Steal):", $17}'
Значение метрики %st обязано строго равняться 0.0%. Если на гипервизоре допущен оверселлинг и показатель CPU Steal Time подскакивает выше 0.5–1%, стек сталкивается с задержками планировщика ядра Linux. Это вызывает резкий рост задержек latency p99 при выполнении транзакций PostgreSQL, задержки в системных вызовах epoll_wait и сброс постоянных WebSocket-сессий сервисом Realtime. Для стабильного продакшена требуются серверные процессоры с высокой частотой на ядро и предсказуемой шиной памяти — например, современные чипы линейки AMD EPYC или высокочастотные Intel Xeon.
Оперативная память и профили RAM Sizing
Грамотный RAM sizing исключает аварийное вмешательство Linux OOM Killer, который при нехватке страниц физической памяти в первую очередь принудительно завершает ресурсоемкие процессы PostgreSQL (postgres: writer process) или веб-сервер Kong.
При расчете оперативной памяти необходимо учитывать аппетиты компонентов стека: * PostgreSQL: параметр shared_buffers резервирует от 25% до 40% всей RAM ноды под внутренний буферный кэш, плюс требуется запас под клиентские соединения (work_mem * max_connections). * Supabase Realtime (Erlang VM): потребляет от 500 МБ до нескольких гигабайт в зависимости от количества открытых сокетов (каждый процесс канала в BEAM аллоцирует базовые структуры памяти). * Служебные контейнеры: GoTrue, PostgREST, Storage API и Kong суммарно требуют от 1.5 до 2.5 ГБ RAM в базовом состоянии. * Page Cache Linux: оставшийся объем свободной RAM ядро использует для буферизации дисковых страниц, что снижает нагрузку на дисковую подсистему при повторяющихся выборках.
Для тестовых стендов абсолютным минимумом являются 2 vCPU и 4 ГБ RAM. Однако в боевых условиях попытка запустить стек на 4 ГБ памяти приводит к постоянному своппингу при выполнении миграций или тяжелых аналитических агрегаций. Полноценное production-окружение требует от 16 ГБ RAM.
Требования к дисковой подсистеме: NVMe IOPS и сброс WAL
Транзакционная надежность PostgreSQL опирается на упреждающую запись в журнал предзаписи (Write-Ahead Logging, WAL). Каждая операция COMMIT при стандартном параметре synchronous_commit = on требует физического сброса блока данных на накопитель с помощью системного вызова fdatasync().
Традиционные SATA SSD и сетевые блочные хранилища с задержками передачи по сети создают узкое горлышко: транзакции встают в ожидание события IO:WALSync. Развертывание продуктивного стека Supabase на VPS требует сертифицированных серверных накопителей NVMe с интерфейсом PCIe 4.0. Базовый критерий дисковой подсистемы — производительность на мелкоблочных операциях со случайным доступом: случайное чтение и запись 4K QD1 с показателем свыше 50 000 NVMe IOPS при постоянной задержке записи менее 200 мкс.
Валидацию дисковой задержки и пропускной способности перед установкой Docker-контейнеров выполняют утилитой fio:
fio --name=wal_latency_test --filename=/tmp/fio_test.bin --size=2G \
--rw=randwrite --bs=4k --direct=1 --ioengine=sync --iodepth=1 \
--runtime=30 --time_based --group_reporting
Если по результатам бенчмарка средний clat (completion latency) превышает 0.5–1 мс, синхронная запись WAL станет критическим барьером масштабирования базы данных.
Сетевая подсистема и параметры портов
Инфраструктура виртуальной машины должна обеспечивать симметричную пропускную способность от 1 до 10 Гбит/с. Для минимизации задержек при передаче медиафайлов через Storage API и постоянных стримов данных Realtime на уровне сетевого стека ядра Linux настраивается алгоритм контроля перегрузок TCP BBR:
# Проверка текущего алгоритма контроля перегрузок
sysctl net.ipv4.tcp_congestion_control
# Активация BBR в ядре Linux
cat <<EOF > /etc/sysctl.d/99-network-bbr.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
net.core.somaxconn = 4096
EOF
sysctl --system
Серверу необходим чистый статический публичный IPv4-адрес без ограничений и фильтрации сервисных портов (80, 443 для шлюза, 5432 для прямого доступа к PostgreSQL, 8000/8443 для Kong API). Использование NAT VPS с пробросом портов неприемлемо из-за проблем с формированием заголовков авторизации и CORS.
В качестве надежного аппаратного базиса для развертывания стека выступают виртуальные серверы провайдера tropic.host. Инфраструктура платформы построена на чистой аппаратной виртуализации KVM без оверселлинга с физической гарантией отсутствия CPU Steal Time (%st = 0.0%), высокопроизводительных процессорах AMD EPYC, серверных накопителях NVMe PCIe 4.0 корпоративного класса и аплинках 1–10 Гбит/с с поддержкой TCP BBR в прямых точках обмена трафиком (Франкфурт, Амстердам, Стамбул).
Матрица сайзинга KVM-сервера под различные профили нагрузки Supabase
| Профиль нагрузки | Целевые метрики нагрузки | Аппаратная конфигурация (vCPU, RAM, Диск) | Сетевой стек и параметры ядра | Рекомендуемый профиль на tropic.host |
|---|---|---|---|---|
| Development / Staging | До 50 RPS, < 500 активных сессий WebSockets, тестовые БД до 5 ГБ | 2 vCPU (AMD EPYC) 4 ГБ RAM 40 ГБ NVMe PCIe 4.0 |
1 Гбит/с, TCP BBR,shared_buffers = 1GB,max_connections = 60 |
KVM Starter (2 vCPU / 4 ГБ RAM / 40 ГБ NVMe) |
| Production Standard | 100–500 RPS, до 5 000 сокетов Realtime, хранилище до 100 ГБ, Auth-нагрузка | 4 vCPU (AMD EPYC) 16 ГБ RAM 160 ГБ NVMe PCIe 4.0 |
1–2.5 Гбит/с, TCP BBR,shared_buffers = 4GB,effective_cache_size = 12GB,work_mem = 32MB |
KVM Pro (4 vCPU / 16 ГБ RAM / 160 ГБ NVMe) |
| High-Load & pgvector | 500–2 000 RPS, 20 000+ Realtime-соединений, тяжелый векторный поиск (HNSW), БД 200+ ГБ | 8 vCPU (AMD EPYC) 32 ГБ RAM 320–600 ГБ NVMe PCIe 4.0 |
2.5–10 Гбит/с, BBR + FQ,shared_buffers = 8GB,maintenance_work_mem = 2GB,индексы векторов в RAM |
KVM Enterprise (8 vCPU / 32 ГБ RAM / 320 ГБ NVMe) |
| Enterprise / Multi-tenant | 2 000+ RPS, терабайтные объемы Storage, десятки тысяч конкурентных транзакций | 16–32 vCPU (AMD EPYC) 64–128 ГБ RAM 1+ ТБ NVMe PCIe 4.0 RAID10 |
10 Гбит/с резервированный канал, выделенный пул под PostgREST, внешний PgBouncer, BBR |
KVM Ultra / Dedicated (16–32 vCPU / 64–128 ГБ RAM / NVMe) |
Архитектура Self-Hosted Supabase: разбор ключевых микросервисов
Развертывание Supabase на VPS представляет собой запуск распределенного кластера из более чем десяти изолированных контейнеров, связанных через внутреннюю bridge-сеть Docker. Вместо монолитной реализации платформа декомпозирует функции BaaS (Backend-as-a-Service) на специализированные демоны, где реляционная СУБД выступает не просто хранилищем строк, а центральной шиной координации данных, событий и политик безопасности.
Архитектура стека в инсталляции supabase self hosted vps логически разделена на четыре эшелона: пограничный обратный прокси-шлюз, прикладные сервисы автогенерации API и авторизации, транзакционный пулер с расширенным ядром базы данных и вспомогательные сервисы телеметрии.
[ Входящий HTTPS / WSS Трафик ]
│
▼
┌──────────────────────────────────────┐
│ Kong API Gateway (:8000) │
│ - Маршрутизация путей (/rest, /auth)│
│ - Предварительная валидация JWT │
└─┬──────────────┬─────────────┬───────┘
│ │ │
┌────────┴──────┐ ┌─────┴──────┐ ┌────┴────────┐
│ GoTrue (:9999)│ │ PostgREST │ │ Realtime │
│ Auth API │ │ (:3000) │ │ (:4000) │
└───────┬───────┘ └─────┬──────┘ └────┬────────┘
│ │ │
│ ┌─────▼────────┐ │ (WAL / pgoutput)
└────────►│ Supavisor │◄───┘
│ (:5432/:6543)│
└─────┬────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ PostgreSQL 15+ Core │
│ Extensions: pgvector, pgsodium, vault, pg_cron │
│ Безопасность: Row Level Security (RLS) │
└─────────────────────────────────────────────────┘
Пограничный маршрутизатор: Kong API Gateway
Kong функционирует в качестве единой точки входа (Edge Proxy) для всех клиентских SDK и веб-панели. Сервис слушает внешний порт 8000 (HTTP) и 8443 (HTTPS) и исключает необходимость прямого проброса портов внутренних микросервисов во внешнюю сеть хоста.
Ключевые зоны ответственности Kong: 1. Префиксная маршрутизация: Разбор URI и проксирование трафика на локальные порты Docker: - /auth/v1/* $\rightarrow$ GoTrue (порт 9999) - /rest/v1/* $\rightarrow$ PostgREST (порт 3000) - /realtime/v1/* $\rightarrow$ Realtime engine (порт 4000) - /storage/v1/* $\rightarrow$ Storage API (порт 5000) 2. Stateless-валидация JWT: Kong инспектирует заголовок Authorization: Bearer <token> до передачи пакета во внутренние сервисы. Проверка криптографической подписи HMAC-SHA256 (JWT_SECRET) или асимметричного ключа RS256 выполняется непосредственно в памяти процесса OpenResty/Nginx. Запросы с невалидным, истекшим или поврежденным токеном отсекаются с кодом 401 Unauthorized на периметре, предотвращая перегрузку прикладных бэкендов нелегитимным трафиком. 3. Инъекция сервисных заголовков: После валидации токена Kong транслирует извлеченные клеймы (Claims) в заголовки апстрима: X-Consumer-Custom-ID (UUID пользователя) и X-Consumer-Username (роль: anon, authenticated или service_role).
Реляционный фундамент: PostgreSQL 15+ и расширения ядра
Центральным компонентом системы является кастомизированный образ PostgreSQL 15/16. В архитектуре Supabase база данных берет на себя исполнение бизнес-логики посредством механизма Row Level Security (RLS). Доступ к строкам таблиц изолируется на уровне SQL-движка: встроенная функция auth.uid() считывает системную переменную сессии request.jwt.claim.sub, переданную через PostgREST, и применяет декларативные политики (CREATE POLICY).
Для реализации профильных сценариев образ СУБД компилируется со специализированным набором расширений: * pgvector: Предоставляет типы данных vector (до 16 000 измерений) и алгоритмы индексации HNSW (Hierarchical Navigable Small World) и IVFFlat для векторизации данных, семантического поиска и работы с моделями эмбеддингов. * pgsodium: Обеспечивает криптографическую защиту данных на уровне колонок (Deterministic/Non-deterministic Authenticated Encryption) через интерфейс библиотеки libsodium. Управление ключами вынесено за пределы обычных SQL-таблиц. * vault: Изолированная схема для безопасного хранения конфиденциальных переменных (API-ключей сторонних сервисов, webhook secrets, сертификатов) с шифрованием на стороне ядра. * pg_cron: Встроенный в ядро планировщик задач. Запускает периодические SQL-функции, агрегацию данных и очистку устаревших сессий по расписанию cron без необходимости внешних демонов в Linux.
Прикладной слой: GoTrue, PostgREST и Realtime
Поверх СУБД развернуто трио независимых сервисов, формирующих основной API-интерфейс платформы:
1. GoTrue (Auth Service)
Написанный на Go микросервис аутентификации и управления жизненным циклом пользователей. Он напрямую модифицирует схему auth в PostgreSQL: - Обрабатывает регистрацию по Email/Паролю, Magic Links, OTP и интеграцию с провайдерами OAuth2 (GitHub, Google, Apple) / SAML 2.0. - Выпускает пары Access Token (короткоживущий JWT, по умолчанию 3600 секунд) и Refresh Token (хранится в таблице auth.refresh_tokens). - Генерирует системные события через PostgreSQL Triggers при создании пользователей, позволяя автоматически инициализировать профили в схеме public.
2. PostgREST
Бинарный сервис на языке Haskell, транслирующий HTTP-запросы в семантически эквивалентные SQL-запросы на лету. - Нулевой overhead парсинга: При старте PostgREST инспектирует схемы БД (public, storage) и строит карту внешних ключей, представлений и RPC-функций. Обновление схемы выполняется без перезапуска демона через системную команду NOTIFY pgrst, 'reload schema'. - Сериализация: Построение ответа в формате JSON делегировано внутренним методам базы данных (json_agg(), row_to_json()), что обеспечивает задержку сериализации (p99 latency) на уровне менее 1–2 мс при нагрузках в тысячи запросов в секунду. - Имперсонация сессий: Каждый запрос к PostgREST открывает транзакцию, в которой выставляются локальные переменные SET LOCAL role и SET LOCAL request.jwt.claims. Это передает управление правами доступа подсистеме RLS СУБД.
3. Realtime Engine
Сервис на базе Erlang VM (BEAM) и фреймворка Phoenix, предназначенный для организации WebSocket-соединений с высокой плотностью конкурентных сессий. - Захват изменений через WAL: Демон подключается к PostgreSQL через протокол логической репликации (слот репликации supabase_realtime с декодером pgoutput или wal2json). - Трансляция событий: Изменения таблиц (INSERT, UPDATE, DELETE) перехватываются на этапе записи в WAL, валидируются на соответствие RLS-политикам для конкретного подключенного токена пользователя и рассылаются подписчикам по каналам Broadcast, Presence или Postgres Changes.
Пулинг и вспомогательная инфраструктура: Supavisor, Storage, Studio, Vector
Вспомогательный контур отвечает за стабильность ввода-вывода, сетевых соединений и администрирование:
- Supavisor: Транзакционный и сессионный пулер соединений следующего поколения, разработанный командой Supabase на Elixir. Он решает архитектурную проблему PostgreSQL, где каждый форк процесса (
backend) потребляет 5–10 МБ оперативной памяти. Supavisor принимает до десятков тысяч входящих TCP-соединений от бессерверных функций (Edge Functions) на внешних портах5432и6543, мультиплексируя их в компактный пул (например, 30–50 физических соединений) к СУБД. - Storage API: Сервис на базе Node.js/Fastify, реализующий объектное хранилище (файлы, изображения, медиа). Метаданные файлов и бакеты фиксируются в таблицах схемы
storage, а бинарные объекты сохраняются либо в локальную файловую систему хоста (volume mount), либо в S3-совместимые бакеты. Проверка прав на скачивание или запись файла проверяется стандартными RLS-правилами PostgreSQL. - Supabase Studio: Графическая панель управления на стеке Next.js (порт
3000). Позволяет управлять схемой таблиц, просматривать логи, редактировать политики RLS, выполнять произвольные SQL-скрипты и настраивать триггеры. В изолированном окружении Studio связывается с СУБД и Kong через служебные сервисные токены. - Vector: Высокопроизводительный агент сбора и маршрутизации логов, написанный на Rust. Vector считывает потоки stdout/stderr со всех соседних Docker-контейнеров, парсит структурированные JSON-логи и сбрасывает их в аналитическую схему базы данных
_analyticsдля последующего отображения в Studio, предотвращая бесконтрольное разрастание локальных Docker log-файлов на диске.
Сводная матрица микросервисов стека Supabase
| Микросервис | Стек / Технология | Внутренний порт | Назначение и функции | Потребление RAM (Baseline) | Критические зависимости |
|---|---|---|---|---|---|
| Kong | OpenResty (Nginx + Lua) | 8000 (HTTP)8443 (HTTPS) |
API Gateway, маршрутизация эндпоинтов, валидация JWT на границе | 120–250 МБ | Нет |
| PostgreSQL | C / Custom Extensions | 5432 |
Реляционная СУБД, выполнение RLS, хранение схем auth/storage/data | 1–8 ГБ+ (зависит от shared_buffers) |
Локальный том хранения данных |
| Supavisor | Elixir (BEAM) | 5432 (Session)6543 (Transaction) |
Масштабируемый пулер соединений, защита СУБД от истощения пула процессов | 150–350 МБ | PostgreSQL |
| PostgREST | Haskell | 3000 |
Автоматическая генерация RESTful API на базе схемы PostgreSQL | 60–180 МБ | PostgreSQL / Supavisor |
| GoTrue | Go | 9999 |
Сервер аутентификации, генерация токенов, интеграция OAuth/MFA | 50–120 МБ | PostgreSQL (схема auth) |
| Realtime | Elixir (Phoenix) | 4000 |
WebSocket сервер, логическое декодирование WAL, pub/sub шина | 180–400 МБ | PostgreSQL (Replication Slot) |
| Storage API | Node.js (Fastify) | 5000 |
Управление объектными бакетами, валидация RLS на загрузку/чтение | 100–220 МБ | PostgreSQL, S3/Локальный диск |
| Studio | TypeScript (Next.js) | 3000 |
Веб-интерфейс администратора, SQL-редактор, визуализатор схемы | 200–450 МБ | Kong, PostgreSQL |
| Vector | Rust | — (Sidecar agent) |
Агрегация stdout/stderr логов контейнеров, очистка, запись в аналитику | 40–90 МБ | Docker Socket, PostgreSQL |
Системные требования к дисковой подсистеме и изоляции vCPU
Одновременное исполнение виртуальной машины Erlang (BEAM в Realtime и Supavisor), компилятора PostgREST и фоновых воркеров PostgreSQL генерирует специфический профиль системных вызовов с высокой частотой контекстных переключений процессов (context switches) и постоянными дисковыми операциями fsync() при фиксации транзакций в WAL.
В условиях применения контейнерной виртуализации уровня ОС (OpenVZ/LXC) разделение процессорного времени и дисковых квот подвержено деградации из-за активности соседних контейнеров на физической ноде, что приводит к росту задержек p99 на транзакциях Realtime.
Для поддержания стабильной работы стека Supabase на VPS критически необходима аппаратная виртуализация KVM с полным отсутствием оверселлинга процессорных ресурсов. На облачной платформе tropic.host конфигурации виртуальных серверов строятся на базе физически изолированных vCPU (AMD EPYC / Ryzen 9) со строгим показателем CPU Steal Time (%st = 0.0%). Серверные накопители NVMe корпоративного класса (интерфейс PCIe 4.0) обеспечивают производительность случайного чтения и записи блоков 4K (QD1) на уровне более 50 000 IOPS, исключая задержки при сбросе буферов PostgreSQL (checkpoint_completion_target) на диск. Сетевые аплинки пропускной способностью от 1 до 10 Гбит/с с активированным алгоритмом congestion control TCP BBR и прямым BGP-маршрутом через узлы Франкфурта (Equinix FR2), Амстердама и Стамбула гарантируют субмиллисекундный отклик пограничного шлюза Kong и стабильный транспорт для десятков тысяч постоянных WebSocket-соединений. Оплата инстансов доступна без скрытых комиссий с помощью международных карт и криптовалют (USDT TRC20, TON, BTC).
Подготовка операционной системы и настройка окружения Docker
Развертывание стека начинается на чистом инстансе под управлением Ubuntu 24.04 LTS или Debian 12. Шаблоны операционных систем, развернутые на KVM-инфраструктуре tropic.host, поставляются с актуальной веткой ядра Linux 6.8+, чистым публичным IPv4 и нативной поддержкой иерархии cgroups v2. Это исключает конфликты изоляции памяти и процессорных лимитов контейнеров на уровне ядра.
Базовый харденинг ОС и изоляция SSH
Работа под учетной записью root в производственной среде недопустима. Первичная инициализация включает создание системного пользователя с привилегиями sudo, генерацию каталога авторизованных ключей и полное отключение парольной аутентификации в демоне OpenSSH:
# Обновление индекса пакетов и компонентов базовой системы
apt update && apt upgrade -y
# Создание сервисного пользователя deployer с оболочкой Bash
useradd -m -s /bin/bash deployer
usermod -aG sudo deployer
# Перенос публичного SSH-ключа администратора
mkdir -p /home/deployer/.ssh
cp /root/.ssh/authorized_keys /home/deployer/.ssh/
chown -R deployer:deployer /home/deployer/.ssh
chmod 700 /home/deployer/.ssh
chmod 600 /home/deployer/.ssh/authorized_keys
Для блокировки векторов подбора паролей и запрета прямого входа суперпользователя конфигурация SSH выносится в изолированный файл /etc/ssh/sshd_config.d/99-security.conf:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
AuthenticationMethods publickey
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
Применение параметров выполняется перезапуском сервиса: systemctl restart ssh (в Debian 12) или systemctl restart ssh.service (в Ubuntu 24.04 LTS).
Тюнинг сетевого стека ядра Linux и дескрипторов sysctl
Стек Supabase объединяет API-шлюз Kong, брокер событий Realtime и пул соединений Supavisor. Высокая плотность входящих TCP-сессий требует пересмотра стандартных лимитов сокетов, очередей синхронизации и файловых дескрипторов ядра.
Алгоритм контроля перегрузки сети tcp bbr в связке с дисциплиной очередей fq (Fair Queuing) минимизирует задержки доставки пакетов при пограничном дропе и обеспечивает максимальную утилизацию канала 1–10 Гбит/с без раздувания буферов (bufferbloat).
Создайте файл /etc/sysctl.d/99-supabase-tuning.conf:
# Активация алгоритма TCP BBR и планировщика очередей FQ
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# Расширение очередей ожидания сокетов под высокие пиковые нагрузки
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 16384
# Буферы приема и отправки TCP (минимальный, по умолчанию, максимальный)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# Оптимизация обработки закрытых соединений (предотвращение TIME_WAIT exhaustion)
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
# Системные лимиты дескрипторов и областей памяти
fs.file-max = 2097152
vm.max_map_count = 262144
Для немедленной активации параметров выполните чтение конфигурации через sysctl:
sysctl --system
Проверка фактической работы BBR и статуса единой иерархии контрольных групп cgroups v2:
# Валидация алгоритма congestion control
sysctl net.ipv4.tcp_congestion_control
# Вывод должен возвратить: net.ipv4.tcp_congestion_control = bbr
# Проверка файловой системы cgroups v2
stat -fc %T /sys/fs/cgroup
# Вывод: cgroup2fs
Сетевая фильтрация через UFW и защита портов
Периметр безопасности требует блокировки всех портов, кроме точек входа веб-трафика и защищенного порта управления. При установке Supabase на VPS в Docker стандартная связка iptables и Docker Engine создает критическую уязвимость: демон Docker по умолчанию публикует порты контейнеров в обход цепочек входящей фильтрации межсетевого экрана ufw.
Все внутренние микросервисы (база PostgreSQL на порту 5432, пул Supavisor на 6543, Vector на 9001) в целевом файле окружения должны проксироваться исключительно через шлюз Kong или биндиться на локальный сокет 127.0.0.1.
Настройка базовых политик ufw:
# Установка политик по умолчанию
ufw default deny incoming
ufw default allow outgoing
# Открытие портов внешнего доступа
ufw allow 22/tcp comment 'SSH Management'
ufw allow 80/tcp comment 'HTTP ACME Challenge'
ufw allow 443/tcp comment 'HTTPS Kong Gateway'
# Активация брандмауэра
ufw --force enable
ufw status verbose
Установка Docker Engine и плагина Docker Compose v2
Пакеты из стандартных репозиториев дистрибутивов (такие как docker.io) содержат устаревшие версии среды исполнения без оперативных патчей безопасности. Установка выполняется строго из официального репозитория Docker Inc. с подключением плагина docker compose v2.
# Установка базовых утилит валидации сертификатов и работы с репозиториями
apt install -y ca-certificates curl gnupg lsb-release
# Создание каталога и импорт доверенного GPG-ключа Docker
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release && echo "$ID")/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# Подключение официального APT-репозитория
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$(. /etc/os-release && echo "$ID") \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
# Установка компонентов Docker Engine
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
После завершения инсталляции сервисного пользователя включают в группу docker, что позволяет управлять контейнерами без повышения привилегий до sudo:
usermod -aG docker deployer
Ротация логов демона Docker
Стек Supabase генерирует массивный поток структурированных логов при интенсивных HTTP/PostgREST и WebSocket-запросах. Без ротации стандартный драйвер json-file заполняет свободное пространство на диске, приводя к аварийной остановке PostgreSQL из-за невозможности записи WAL.
Конфигурация глобальной ротации фиксируется в /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "20m",
"max-file": "3"
},
"exec-opts": ["native.cgroupdriver=systemd"],
"features": {
"buildkit": true
}
}
Перезапуск и верификация работоспособности окружения:
systemctl restart docker
systemctl enable docker
# Проверка версий ядра Docker и плагина Docker Compose v2
docker --version
docker compose version
Корректный вывод подтверждает готовность операционной системы к загрузке официального репозитория и конфигурации сетевых сервисов Supabase.
Пошаговое развертывание Supabase через официальный Docker Compose
Для изоляции сервисов стека выделяется рабочий каталог /opt/supabase. Официальный репозиторий проекта представляет собой монорепозиторий, поэтому для экономии дискового пространства и ускорения развертывания выполняется мелкое клонирование (--depth 1) с переходом в подкаталог docker, где сосредоточены манифесты Docker Compose и конфигурационные шаблоны сервисов.
Клонирование репозитория и файловая структура
Загрузка компонентов осуществляется от имени непривилегированного пользователя deployer:
sudo mkdir -p /opt/supabase
sudo chown -R deployer:deployer /opt/supabase
cd /opt/supabase
# Клонирование только последнего коммита репозитория
git clone --depth 1 https://github.com/supabase/supabase.git .
cd docker
В каталоге docker сосредоточены ключевые директории и файлы: * docker-compose.yml — центральный оркестрационный файл, объединяющий контейнеры PostgreSQL (с расширениями pgvector, pg_cron, pgjwt), PostgREST, GoTrue (Auth), Kong (API Gateway), Realtime, Storage, Vector (лог-коллектор) и Studio UI. * volumes/ — локальные точки монтирования данных: * volumes/db/data/ — персистентное хранилище реляционной СУБД; * volumes/storage/ — локальные бакеты S3-совместимого объектного хранилища; * volumes/api/ — конфигурационные схемы маршрутизации шлюза Kong.
При эксплуатации Supabase на VPS провайдера tropic.host аппаратная виртуализация KVM исключает конкуренцию за системные ресурсы ядра (%st = 0.0%). Серверные NVMe-диски PCIe 4.0 со скоростью случайных операций 4K QD1 свыше 50 000 IOPS предотвращают рост показателя iowait в момент синхронизации WAL-логов, когда смонтированные volumes базы данных испытывают пиковые нагрузки записи.
Конфигурация параметров окружения (.env setup)
Шаблон переменных среды содержит базовые параметры портов, лимитов памяти, пулов соединений и криптографических ключей. Первичный env setup начинается с копирования дефолтного файла:
cp .env.example .env
chmod 600 .env
Файл .env содержит базовые параметры, обязательные к изменению перед первым запуском. Критически важные переменные:
# Сетевая привязка API Gateway (Kong)
KONG_HTTP_PORT=8000
KONG_HTTPS_PORT=8443
# Учетные данные СУБД PostgreSQL
POSTGRES_PASSWORD=Сгенерированный_Надежный_Пароль_DB
POSTGRES_DB=postgres
POSTGRES_PORT=5432
# Доступ к административной панели Supabase Studio
STUDIO_PORT=3000
STUDIO_DEFAULT_ORGANIZATION=Production
STUDIO_DEFAULT_PROJECT=Default
# Внешний URL для клиентских SDK и редиректов OAuth
API_EXTERNAL_URL=http://<IP_АДРЕС_СЕРВЕРА>:8000
Ограничение прав доступа chmod 600 .env предотвращает чтение паролей СУБД и сервисных ключей процессами других непривилегированных пользователей операционной системы.Первичный запуск стека через Docker Compose
Перед стартом контейнеров выполняется предварительная загрузка образов из реестра, что минимизирует время простоя при инициализации сетевых пространств имен:
# Предзагрузка слоев образов
docker compose pull
# Фоновый запуск всех микросервисов стека
docker compose up -d
Команда docker compose up -d развертывает выделенную виртуальную сеть Docker bridge, монтирует дисковые тома volumes и запускает контейнеры в строгом порядке с учетом директив depends_on.
Первым инициализируется контейнер СУБД (supabase-db), выполняя накат базовых системных миграций и инициализацию расширений. Следом запускаются зависимые микросервисы (GoTrue, PostgREST, Realtime, Storage), подключающиеся к сокету PostgreSQL, после чего шлюз Kong начинает маршрутизацию входящего трафика.
Диагностика статуса контейнеров и аудит журналов
Контроль запущенных микросервисов выполняется командой:
docker compose ps
Вывод должен содержать статус Up (или Up (healthy)) для всех сервисов:
NAME IMAGE COMMAND SERVICE STATUS
supabase-analytics timberio/vector:0.28.1-alpine "vector --config /et…" analytics Up
supabase-auth supabase/gotrue:v2.158.1 "gotrue" auth Up (healthy)
supabase-db supabase/postgres:15.6.1.143 "docker-entrypoint.s…" db Up (healthy)
supabase-kong kong:2.8.1 "/docker-entrypoint.…" kong Up (healthy)
supabase-meta supabase/postgres-meta:v0.84.2 "node dist/server/se…" meta Up
supabase-postgrest postgrest/postgrest:v12.2.0 "postgrest" rest Up
supabase-realtime supabase/realtime:v2.33.59 "/app/bin/server" realtime Up
supabase-storage supabase/storage-api:v1.11.13 "docker-entrypoint.s…" storage Up (healthy)
supabase-studio supabase/studio:20240729-e58f276 "node apps/studio/di…" studio Up
Для выявления скрытых ошибок инициализации (таймауты подключения к БД, сбои синтаксиса .env, конфликты сокетов) выполняется потоковый аудит логов:
# Просмотр стартовых логов ядра базы данных
docker compose logs -f --tail=100 db
# Комплексный аудит ошибок всех компонентов
docker compose logs --tail=50 | grep -Ei "error|fatal|panic|refused"
Штатный запуск supabase-db подтверждается записями: * database system is ready to accept connections * Успешное выполнение миграций без возврата кодов завершения exit code 1.
Если статус одного из контейнеров переходит в Restarting или Exited, локализация сбоя проводится по изолированному выводу сервиса (например, docker compose logs auth для проверки подключения сервиса GoTrue к пулу соединений PostgreSQL).
Генерация криптографических секретов и харденинг .env
При развертывании инфраструктуры для supabase на vps ключевое значение имеют реальные аппаратные метрики хостинга.
Ключевые инженерные аспекты:
- Генерация криптостойких паролей PostgreSQL и JWT_SECRET с использованием утилиты openssl rand: Проверяйте параметры изоляции ресурсов и отсутствие оверселлинга.
- Расчет новых токенов ANON_KEY и SERVICE_ROLE_KEY с зашитыми правами доступа: Проверяйте параметры изоляции ресурсов и отсутствие оверселлинга.
- Настройка учетных данных администратора для входа в панель Supabase Studio (DASHBOARD_USERNAME и DASHBOARD_PASSWORD): Проверяйте параметры изоляции ресурсов и отсутствие оверселлинга.
- Безопасная смена секретов вебхуков и ключей дешифрования хранилища: Проверяйте параметры изоляции ресурсов и отсутствие оверселлинга.
Публикация сервиса: Nginx Reverse Proxy, Let's Encrypt SSL и WebSockets
После изоляции портов стека во внутреннем сетевом контуре хоста (127.0.0.1:8000 для Kong API Gateway и 127.0.0.1:3000 для Supabase Studio) требуется развернуть граничный шлюз. Прямое выставление внутренних портов контейнеров в публичный интернет недопустимо: для промышленной эксплуатации Supabase на VPS необходима терминация TLS, защита от перегрузок буферов соединений и принудительная фильтрация аномального трафика.
Для маршрутизации запросов используется связка из внешнего DNS, веб-сервера Nginx в роли обратного прокси и автоматизированного выпуска сертификатов. Благодаря полной аппаратной KVM-виртуализации на tropic.host ядро гостевой ОС имеет прямой доступ к сетевому стеку без ограничений пространств имен сетевых адаптеров (в отличие от контейнерных сред OpenVZ), что позволяет оптимизировать сокеты под удержание сотен тысяч одновременных сессий.
DNS-маршрутизация и подготовка сетевого стека
На стороне авторитетного DNS-провайдера создаются записи типа A, указывающие на выделенный статический IPv4-адрес сервера:
api.yourdomain.com. IN A 194.xxx.xxx.xxx
studio.yourdomain.com. IN A 194.xxx.xxx.xxx
Для минимизации задержек при обработке постоянных TCP-сессий и handshake-пакетов активируйте алгоритм контроля перегрузок TCP BBR на уровне ядра Linux. На серверных узлах tropic.host с симметричными аплинками 1–10 Гбит/с и прямыми BGP-стыками в точках обмена трафиком (Франкфурт Equinix FR2, Амстердам NIKHEF) это гарантирует стабильный latency p99 даже при пиковой утилизации полосы:
cat << 'EOF' >> /etc/sysctl.d/99-network-tuning.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
EOF
sysctl --system
Автоматизированный выпуск SSL/TLS через Certbot
Для получения доверенных сертификатов от центра сертификации Let's Encrypt установите утилиту Certbot и модуль интеграции с Nginx:
apt-get update && apt-get install -y nginx certbot python3-certbot-nginx
Перед генерацией итоговой конфигурации виртуального хоста выпустите первичный ssl certificate с помощью временного standalone-вызова или базового профиля валидации:
certbot certonly --nginx \
--agree-tos \
--no-eff-email \
--email [email protected] \
-d api.yourdomain.com \
-d studio.yourdomain.com
Процесс Certbot проверяет владение доменами по протоколу ACME HTTP-01 и сохраняет криптографические цепочки в директорию /etc/letsencrypt/live/api.yourdomain.com/. Автоматическое продление управляется встроенным системным таймером systemd (certbot.timer). Проверьте корректность сценария ротации:
certbot renew --dry-run
Для усиления криптостойкости сгенерируйте кастомные параметры Диффи-Хеллмана:
openssl dhparam -out /etc/nginx/dhparam.pem 2048
Конфигурация Nginx: Rate Limiting и WebSocket Proxy
Основная специфика работы API-шлюза Supabase — постоянные дуплексные соединения сервиса Realtime, работающего поверх протокола WebSocket. Если стандартный HTTP-прокси закрывает соединение по тайм-ауту неактивности через 60 секунд, то websocket proxy обязан корректно обрабатывать заголовки Upgrade и Connection, а также удерживать открытый канал между клиентом и бэкендом без сброса TCP-сессии.
Создайте конфигурационный файл виртуального хоста /etc/nginx/sites-available/supabase.conf:
# Определение заголовков для корректного апгрейда протокола до WebSockets
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Зоны ограничения частоты запросов (Rate Limiting)
# 10 МБ памяти вмещают ~160 000 уникальных IP-адресов
limit_req_zone $binary_remote_addr zone=api_general:10m rate=50r/s;
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=addr_limit:10m;
# Редирект незашифрованного HTTP-трафика на HTTPS
server {
listen 80;
listen [::]:80;
server_name api.yourdomain.com studio.yourdomain.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
# Виртуальный хост для публичного API и Realtime (Kong)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.yourdomain.com;
# TLS-параметры
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Заголовки безопасности
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
# Ограничение параллельных TCP-соединений с одного IP
limit_conn addr_limit 50;
# Основной прокси-контур к Kong API Gateway
location / {
limit_req zone=api_general burst=100 nodelay;
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Буферизация для стандартных REST-ответов
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 16 8k;
}
# Защита эндпоинтов аутентификации от перебора учетных записей (Brute-force)
location ~* ^/auth/v1/(token|signup|recover) {
limit_req zone=auth_limit burst=10 nodelay;
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Выделенный блок маршрутизации для Realtime WebSocket каналов
location /realtime/v1/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
# Передача служебных заголовков для переключения протокола
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Отключение буферизации для мгновенной доставки push-событий клиентам
proxy_buffering off;
# Увеличение тайм-аутов удержания неактивной сессии (24 часа)
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
# Виртуальный хост для панели администратора (Studio)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name studio.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
# Ограничение размера загружаемых файлов для Storage-менеджера
client_max_body_size 100M;
location / {
limit_req zone=api_general burst=50 nodelay;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Поддержка WebSocket для встроенных live-инструментов панели
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
}
}
Активируйте виртуальный хост, удалите дефолтный профиль и протестируйте синтаксис директив перед применением изменений:
ln -sf /etc/nginx/sites-available/supabase.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
Проверка работоспособности TLS и сквозного WebSocket-соединения
Для валидации корректности работы внешнего слоя проверьте handshake и заголовки ответа API-шлюза:
curl -I https://api.yourdomain.com/rest/v1/
Код ответа 200 OK или 401 Unauthorized (при отсутствии переданного API-ключа в заголовках) подтверждает, что внешний nginx reverse proxy корректно перенаправляет поток на внутренний сервис Kong.
Для проверки функциональности транспортного слоя realtime и валидации WebSocket-хендшейка выполните диагностический запрос с принудительной передачей заголовков Upgrade:
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
https://api.yourdomain.com/realtime/v1/websocket?apikey=YOUR_ANON_KEY\&vsn=1.0.0
Успешное согласование возвращает HTTP-статус 101 Switching Protocols:
HTTP/1.1 101 Switching Protocols
Server: nginx
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Присутствие статуса 101 подтверждает, что цепочка доверия Letsencrypt активна, сокеты переводятся в потоковый дуплексный режим без разрыва прокси-сервером, а периметр защищен лимитами частоты запросов на сетевом уровне.
Тюнинг производительности PostgreSQL под высокие нагрузки
Стандартный Docker-образ supabase-db поставляется с консервативной конфигурацией, рассчитанной на запуск в окружениях с 1–2 ГБ оперативной памяти. При эксплуатации стека Supabase PostgreSQL на VPS в условиях сотен одновременных транзакций, постоянных WebSocket-подписок Realtime и интенсивных векторных выборок дефолтные параметры приводят к деградации latency p99, частым принудительным контрольным точкам и сбросу промежуточных результатов сортировки во временные файлы на диске.
Для реализации потенциала многоядерных процессоров и скоростных NVMe-накопителей требуется переопределение параметров ядра СУБД через конфигурационный файл или переменные окружения контейнера.
┌────────────────────────────────────────────────────────┐
│ Клиентский трафик (API / Edge) │
└───────────────────────────┬────────────────────────────┘
▼
┌────────────────────────────────────────────────────────┐
│ Supavisor (Порт 6543 / Транзакционный пулер) │
│ Удержание до 10 000 клиентских соединений в пуле │
└───────────────────────────┬────────────────────────────┘
▼ (100–200 постоянных backend-сессий)
┌────────────────────────────────────────────────────────┐
│ PostgreSQL Core (supabase-db) │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ shared_buffers (25%) │ │ OS Page Cache (50%) │ │
│ └──────────┬───────────┘ └──────────┬───────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ WAL & Checkpoint Engine (NVMe I/O) │ │
│ │ checkpoint_completion_target=0.9, max_wal=16-32GB│ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
Калькуляция параметров памяти: shared_buffers, work_mem и effective_cache_size
Распределение оперативной памяти в PostgreSQL опирается на модель разделения обязанностей между собственным буферным пулом СУБД и дисковым кэшем ядра Linux (Page Cache). Непосредственное выделение 80% RAM под процесс PostgreSQL вызовет эффект двойного буферизирования и деградацию файлового ввода-вывода.
1. shared_buffers
- Формула расчета:
RAM × 0.25 - Назначение: Область разделяемой памяти для кэширования страниц таблиц и индексов.
- Ограничение: Значения выше 40% RAM в Linux-системах редко дают прирост производительности из-за накладных расходов на поддержание хэш-таблицы буферов и потерю эффективности упреждающего чтения ядра ОС. Для ноды с 16 ГБ RAM базовое значение составляет
4GB.
2. effective_cache_size
- Формула расчета:
RAM × 0.70 ... 0.75 - Назначение: Эвристический ориентир для оптимизатора запросов (Cost-based Query Planner). Параметр не аллоцирует физическую память, а сообщает планировщику суммарный объем буферов (
shared_buffers+ системный кэш страниц Linux). - Чем выше значение, тем охотнее оптимизатор выбирает сканирование по индексу (
Index Scan/Bitmap Index Scan) вместо последовательного чтения всей таблицы (Seq Scan). Для 16 ГБ RAM параметр устанавливается в12GB.
3. work_mem
- Формула расчета:
((RAM × 0.8) - shared_buffers) / (max_connections × 3) - Назначение: Объем памяти, выделяемый под каждую отдельную операцию сортировки (
ORDER BY), построения хэш-таблицы (Hash Join) или группировки (GROUP BY). - Критический риск: Память выделяется не на транзакцию или сессию, а на каждый узел плана запроса. Сложный запрос с тремя соединениями и сортировкой может потребовать $4 \times \text{work_mem}$. Установка завышенного значения (
>128MB) при прямых подключениях без пулера гарантированно приводит к активации OOM Killer ядра Linux. При использовании пулера соединений безопасный диапазон составляет16MB–64MB.
4. maintenance_work_mem
- Формула расчета:
RAM × 0.05 ... 0.10(не более2GBво избежание блокировок аллокатора). - Назначение: Пул памяти для операций обслуживания: выполнения
VACUUM/AUTOVACUUM, перестроения индексов (REINDEX,CREATE INDEX) и добавления внешних ключей. Высокое значение критически ускоряет генерацию графов векторных индексовpgvector.
Аппаратная матрица сайзинга PostgreSQL
Конфигурации ниже откалиброваны под профили KVM VPS без оверселлинга с нулевым процессорным воровством (%st = 0.0%) и серверными NVMe-дисками (эталон архитектуры узлов tropic.host на процессорах AMD EPYC и Intel Xeon с PCIe 4.0).
| Параметр СУБД | Профиль Starter (4 vCPU / 8 GB RAM) | Профиль Production (8 vCPU / 16 GB RAM) | Профиль Scale (16 vCPU / 32 GB RAM) | Влияние на подсистему и логику планировщика |
|---|---|---|---|---|
shared_buffers |
2GB |
4GB |
8GB |
Буферный кэш страниц СУБД |
effective_cache_size |
6GB |
12GB |
24GB |
Оценка доступной памяти для Query Planner |
work_mem |
16MB |
32MB |
64MB |
Лимит на каждый узел сортировки/хэширования |
maintenance_work_mem |
512MB |
1GB |
2GB |
Память для Autovacuum и сборки индексов |
max_connections |
100 |
150 |
200 |
Физические backend-процессы (остальное в пулере) |
max_wal_size |
8GB |
16GB |
32GB |
Максимальный объем журнала до форсированного чекпоинта |
min_wal_size |
1GB |
2GB |
4GB |
Минимальный резерв предвыделенных WAL-сегментов |
checkpoint_completion_target |
0.9 |
0.9 |
0.9 |
Размытие записи «грязных» страниц во времени |
random_page_cost |
1.1 |
1.1 |
1.1 |
Коэффициент стоимости случайного чтения для NVMe |
effective_io_concurrency |
200 |
256 |
300 |
Глубина очереди асинхронного prefetch ядра |
Тюнинг контрольных точек и WAL-подсистемы под диски NVMe
На дефолтных настройках PostgreSQL сбрасывает контрольные точки (checkpoints) каждые 5 минут или по накоплению 1 ГБ WAL-файлов. В моменты интенсивной вставки данных это провоцирует лавинообразную запись «грязных» страниц из shared_buffers на диск, создавая очереди I/O (I/O spikes) и вызывая скачки latency.
Для устранения дисковых пауз при сбросе WAL на NVMe накопителях применяются следующие параметры:
# /etc/postgresql/custom.conf
# Растягивание записи контрольной точки на 90% интервала
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
# Увеличение лимитов WAL для исключения ранних внеплановых чекпоинтов
max_wal_size = 16GB
min_wal_size = 2GB
wal_buffers = 16MB
# Оптимизация дискового планировщика под сверхбыстрый случайный доступ NVMe
seq_page_cost = 1.0
random_page_cost = 1.1
# Асинхронный prefetching страниц через системные вызовы posix_fadvise
effective_io_concurrency = 256
# Параллелизация сканирования и сборки
max_worker_processes = 8
max_parallel_workers_per_gather = 4
max_parallel_maintenance_workers = 4
Интерпретация критических директив для дисковой подсистемы:
checkpoint_completion_target = 0.9: Указывает СУБД размазывать операцию записи измененных страниц по времени, завершая ее ровно к 90% интервалаcheckpoint_timeout(то есть за 13.5 минут при тайм-ауте в 15 минут). Это срезает пиковые нагрузки на контроллер диска, преобразуя взрывной трафик в плавный фоновый поток.random_page_cost = 1.1: Значение по умолчанию (4.0) рассчитано на устаревшие механические HDD, где случайное позиционирование магнитной головки кратно медленнее последовательного чтения. На enterprise-накопителях NVMe PCIe 4.0 со случайным чтением 4K QD1 свыше 50 000 IOPS задержка случайного доступа сопоставима с последовательным. Установка значения1.1заставляет планировщик использовать индексные сканирования вместо тяжелых проходовSeq Scan.
Оптимизация пула соединений через Supavisor
Каждое прямое подключение к PostgreSQL порождает отдельный процесс операционной системы (fork), потребляющий от 5 до 10 МБ оперативной памяти под служебные структуры сессии и кэш планов запросов. При 500 одновременных подключениях одна только маршрутизация процессов отнимает до 5 ГБ RAM и вызывает частую смену контекста на CPU (context switching), блокируя L3-кэш процессора.
В экосистеме Supabase управление соединениями выполняет Supavisor — распределенный высокопроизводительный пулер соединений, написанный на Elixir/OTP. Он заменяет классический PgBouncer и поддерживает сессионный и транзакционный режимы пулинга.
┌────────────────────────┐ ┌────────────────────────┐
│ Edge Function (HTTP) │ │ Next.js App / NestJS │
└───────────┬────────────┘ └───────────┬────────────┘
│ │
▼ ▼
══════════════════════════════════════════════════════════════════
Порт 6543 (Supavisor Transaction Mode)
══════════════════════════════════════════════════════════════════
│
▼
┌──────────────────────────────────────┐
│ Supavisor Connection Manager │
│ - 5 000+ виртуальных клиентов │
│ - Мультиплексирование транзакций │
└──────────────────┬───────────────────┘
│
▼ (100–150 реальных backend-подключений)
══════════════════════════════════════════════════════════════════
Порт 5432 (PostgreSQL Engine Direct)
══════════════════════════════════════════════════════════════════
Настройка пулера в файле конфигурации окружения стека (docker-compose.yml / .env):
# Ограничение физических подключений самого Postgres
POSTGRES_MAX_CONNECTIONS=150
# Конфигурация пулера Supavisor
POOLER_DEFAULT_POOL_SIZE=20
POOLER_MAX_CLIENT_CONN=5000
POOLER_POOL_MODE=transaction
Режимы работы и маршрутизация: * Порт 6543 (Транзакционный режим): Физическое соединение удерживается сервером только на время фактического выполнения транзакции (BEGIN ... COMMIT). Как только транзакция завершена, коннект возвращается в пул. Этот порт используется для API, микросервисов, бессерверных Edge-функций и ORM (Prisma, Drizzle, TypeORM). * Порт 5432 (Сессионный режим / Direct): Прямое соединение к СУБД. Требуется исключительно для операций миграции структуры (schema migrations, Flyway, Prisma Migrate), временных таблиц, команд LISTEN/NOTIFY и ручного администрирования через psql.
Особенности индексации и распределения памяти для pgvector
Расширение pgvector добавляет в PostgreSQL поддержку эмбеддингов для нейросетевого поиска и RAG-пайплайнов. Производительность векторных индексов определяется тем, помещается ли рабочая структура графа целиком в оперативную память.
Для выборки доступны два типа индексов:
1. HNSW (Hierarchical Navigable Small World)
- Обеспечивает наивысшую скорость поиска с показателем точности (recall) > 98%.
- Индекс представляет собой многоуровневый граф, требующий значительного объема памяти.
Формула оценки объема оперативной памяти под индекс HNSW:
$$\text{RAM}_{\text{index}} \approx \text{Rows} \times \left( \text{Dimensions} \times 4 + M \times 8 \times 2 \right) \times 1.25$$
Где: * $\text{Dimensions}$ — размерность вектора (например, 1536 для text-embedding-3-small от OpenAI). * $M$ — количество двунаправленных связей на узел (стандартно 16 или 24).
-- Генерация HNSW индекса с оптимизированными параметрами памяти
SET maintenance_work_mem = '2GB';
SET max_parallel_maintenance_workers = 4;
CREATE INDEX idx_documents_embedding_hnsw
ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 128);
m = 16: Число ребер на элемент графа. Увеличение до 24 повышает recall, но линейно раздувает размер индекса в RAM.ef_construction = 128: Глубина поиска при построении графа. Определяет качество связей и время первичной индексации.hnsw.ef_search: Параметр времени выполнения запроса. По умолчанию равен40. Для нагруженных API-эндпоинтов регулирует баланс точности и latency:
-- Увеличение точности за счет времени выполнения на уровне транзакции
SET LOCAL hnsw.ef_search = 100;
SELECT id, content
FROM documents
ORDER BY embedding <=> '[0.012, -0.023, ...]'
LIMIT 5;
2. IVFFlat (Inverted File Flat)
- Разбивает векторное пространство на кластеры (списки инвертированного файла) с помощью алгоритма k-means.
- Потребляет значительно меньше памяти, чем HNSW, строится быстрее, но уступает по скорости и страдает от деградации recall при изменении распределения данных.
-- Расчет списков (lists): ориентир ~ sqrt(rows) для <1M строк
CREATE INDEX idx_documents_embedding_ivfflat
ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 1000);
Изоляция ресурсов для pgvector
- Во время сборки графа HNSW СУБД держит все промежуточные структуры в
maintenance_work_mem. Если лимит занижен (<512MB), сборка графа переключается на постоянные промежуточные дампы во временные файлы на накопителе, увеличивая время выполнения операции в 15–20 раз. - Размер индекса HNSW вместе с таблицей не должен превышать суммарную емкость
shared_buffers+ Page Cache. Если граф вытесняется на диск, случайные перемещения по узлам вызывают лавину операций I/O, увеличивая время ответа поиска с 2–5 мс до 150–400 мс.
Применение конфигурации и валидация утилизации буферов
Для активации параметров без пересборки контейнера добавьте том монтирования кастомной конфигурации в секцию сервиса db файла docker-compose.yml:
services:
db:
image: supabase/postgres:15.6.1.143
volumes:
- ./volumes/db/data:/var/lib/postgresql/data
- ./volumes/db/custom.conf:/etc/postgresql/custom.conf:ro
command:
- postgres
- -c
- config_file=/etc/postgresql/custom.conf
Примените изменения и выполните перезагрузку конфигурации демона без прерывания активных клиентских сессий:
docker exec -i supabase-db psql -U postgres -c "SELECT pg_reload_conf();"
Проверьте корректность фактического применения параметров и проверьте коэффициент попадания в буферный кэш (Cache Hit Ratio, целевой показатель для продакшена — не ниже 99.0%):
-- Проверка критических лимитов памяти
SELECT name, setting, unit, context
FROM pg_settings
WHERE name IN ('shared_buffers', 'work_mem', 'maintenance_work_mem', 'effective_cache_size', 'random_page_cost');
-- Анализ коэффициента попадания в кэш страниц
SELECT
sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) * 100.0 AS cache_hit_ratio
FROM pg_statio_user_tables;
Если расчетный cache_hit_ratio опускается ниже 98.5%, это свидетельствует о нехватке shared_buffers либо об избыточных последовательных сканированиях (Seq Scan) крупных таблиц, вымывающих «горячие» страницы из оперативной памяти.
Регламент Disaster Recovery: бэкапы PostgreSQL и план аварийного восстановления
Высокий коэффициент попадания в буферный кэш обеспечивает производительность в штатном режиме, однако стабильность продакшен-инсталляций Supabase на VPS определяется жесткостью целевых метрик RPO (Recovery Point Objective) и RTO (Recovery Time Objective). Для stateful-платформы, объединяющей реляционные данные, метаданные авторизации и бинарные объекты, стратегия disaster recovery строится на двух эшелонах: непрерывная инкрементальная архивация журналов предзаписи (WAL) через WAL-G для минимизации RPO до величины < 60 секунд, а также суточные логические дампы с шифрованием для защиты от логического повреждения схемы и таблиц. При этом развертывание требует исключительно аппаратной виртуализации KVM, так как в контейнерных средах OpenVZ/LXC оверселлинг памяти hypervisor-нодой и отсутствие прямого управления дисковыми барьерами гарантированно приводят к деградации RTO и риску повреждения данных при аварийном сбросе буферов.
Архитектура двухуровневого резервного копирования: WAL-G и шифрованный pg_dump
Непрерывное физическое резервирование реализуется утилитой wal-g. Инструмент осуществляет потоковое сжатие сегментов WAL (алгоритмами lz4 или zstd) и выгружает их в объектное хранилище (s3 backup). Для изоляции доступа используется выделенный IAM-пользователь или S3-токен с правами PutObject и GetObject без возможности безвозвратного удаления объектов политикой бакета (Object Lock / WORM).
В конфигурационный файл PostgreSQL (custom.conf) внедряются директивы непрерывной архивации:
# Режим архивации WAL для WAL-G
wal_level = replica
archive_mode = on
archive_command = 'docker exec -i supabase-db wal-g wal-push %p'
archive_timeout = 60
Создание базового снимка (basebackup) выполняется по расписанию через cron раз в сутки:
# Формирование полного базового снимка кластера в S3
docker exec -i -e WALE_S3_PREFIX="s3://backup-vault/supabase-cluster/wal-g" \
-e AWS_ACCESS_KEY_ID="s3-access-key-id" \
-e AWS_SECRET_ACCESS_KEY="s3-secret-key" \
-e AWS_ENDPOINT="https://s3.eu-central-1.amazonaws.com" \
supabase-db wal-g backup-push /var/lib/postgresql/data
Второй эшелон — создание логического слепка через pg_dump с асимметричным GPG-шифрованием. В отличие от сырых бинарных файлов данных, логический дамп позволяет изолированно восстановить отдельные схемы (public, auth, storage) при случайном повреждении таблиц. Скрипт ежедневной логической архивации запускается хостовым демоном systemd:
#!/usr/bin/env bash
set -Eeuo pipefail
BACKUP_DIR="/tmp/pg_dump_cache"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
DUMP_FILE="${BACKUP_DIR}/supabase_db_${TIMESTAMP}.dump"
ENC_FILE="${DUMP_FILE}.gpg"
S3_URI="s3://backup-vault/supabase-cluster/logical-dumps/"
mkdir -p "${BACKUP_DIR}"
chmod 700 "${BACKUP_DIR}"
# Создание кастомного сжатого дампа кластера
docker exec -i supabase-db pg_dump \
-U postgres \
-F c \
-b \
-v \
-d postgres \
--exclude-table-data='realtime.messages' > "${DUMP_FILE}"
# Асимметричное шифрование открытым GPG-ключом инфраструктуры
gpg --batch --yes --encrypt --recipient "[email protected]" \
--output "${ENC_FILE}" "${DUMP_FILE}"
# Отправка шифрованного артефакта в S3
aws --endpoint-url="https://s3.eu-central-1.amazonaws.com" \
s3 cp "${ENC_FILE}" "${S3_URI}" --storage-class STANDARD_IA
# Зачистка временного буфера с диска
rm -f "${DUMP_FILE}" "${ENC_FILE}"
Развертывание резервной ноды KVM VPS при отказе первичного сервера
При полном выходе из строя основной площадки (аппаратный отказ хост-сервера, сетевой блэкаут дата-центра) регламент требует инициализации независимой виртуальной машины. В качестве эталона инфраструктуры для восстановления продакшена задействуются облачные KVM VPS на платформе tropic.host: чистая аппаратная виртуализация с нулевым оверселлингом (CPU Steal Time %st = 0.0%), высокочастотные ядра AMD EPYC / Ryzen 9 и серверные NVMe накопители PCIe 4.0 (QD1 4K > 50 000 IOPS). Наличие симметричных аплинков 1–10 Гбит/с с оптимизированным сетевым стеком TCP BBR и прямыми стыками в узлах Франкфурта и Амстердама гарантирует выкачивание многогигабайтных дампов из S3 на предельной скорости интерфейса, сокращая критический RTO до технологического минимума.
Подготовка резервного хоста начинается с базовой оптимизации ядра Linux под высокие сетевые и дисковые нагрузки:
# Тюнинг сетевого стека и ограничений файловых дескрипторов
cat <<EOF > /etc/sysctl.d/99-dr-node.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
net.core.somaxconn = 65535
fs.file-max = 2097152
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
EOF
sysctl --system
# Установка зависимостей и развертывание репозитория конфигурации Supabase
apt-get update && apt-get install -y docker.io docker-compose-v2 awscli gnupg zstd
git clone https://github.com/supabase/supabase.git /opt/supabase
cd /opt/supabase/docker
cp .env.example .env
В .env резервного узла переносятся секреты из защищенного хранилища (Vault): POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY.
Валидация целостности дампов и процедура восстановления (Restore Test)
Регулярный restore test исключает накопление поврежденных или неполных снимков. На пустом экземпляре базы данных процедура восстановления выполняется по следующему алгоритму.
- Загрузка шифрованного дампа из объектного хранилища и его расшифровка приватным мастер-ключом:
aws --endpoint-url="https://s3.eu-central-1.amazonaws.com" \
s3 cp s3://backup-vault/supabase-cluster/logical-dumps/latest.dump.gpg /tmp/latest.dump.gpg
gpg --batch --yes --decrypt \
--passphrase-file /root/.gpg-master.pass \
--output /tmp/latest.dump /tmp/latest.dump.gpg
- Валидация содержимого дампа без модификации данных на диске (проверка TOC-заголовков и целостности блоков сжатия):
pg_restore -l /tmp/latest.dump > /dev/null && echo "STATUS: Dump integrity verified"
- Инициализация чистого контейнера
supabase-dbс пустой структурой каталога/var/lib/postgresql/dataи накатка структуры:
docker compose up -d db
# Ожидание готовности сокета PostgreSQL
until docker exec -i supabase-db pg_isready -U postgres; do sleep 2; done
# Восстановление данных с параллелизацией по ядрам процессора (-j)
docker exec -i supabase-db pg_restore \
-U postgres \
-d postgres \
--clean \
--if-exists \
--no-owner \
--no-privileges \
-v < /tmp/latest.dump
Если восстановление выполняется из WAL-G (Point-in-Time Recovery до точного таймстемпа аварии), процедура замещает инициализацию pg_restore:
# Восстановление последнего снимка и настройка наката WAL
docker run --rm -v /opt/supabase/docker/volumes/db/data:/var/lib/postgresql/data \
-e WALE_S3_PREFIX="s3://backup-vault/supabase-cluster/wal-g" \
-e AWS_ACCESS_KEY_ID="s3-access-key-id" \
-e AWS_SECRET_ACCESS_KEY="s3-secret-key" \
supabase/postgres:15.6.1.143 \
wal-g backup-fetch /var/lib/postgresql/data LATEST
# Формирование маркера завершения накатки логов
touch /opt/supabase/docker/volumes/db/data/recovery.signal
cat <<EOF >> /opt/supabase/docker/volumes/db/data/postgresql.auto.conf
restore_command = 'wal-g wal-fetch "%f" "%p"'
recovery_target_time = '2026-10-04 06:15:00+00'
recovery_target_action = 'promote'
EOF
Запуск контейнеров Supabase, синхронизация Storage и проверка клиентов
После перевода PostgreSQL в состояние promoted (чтение-запись) запускается остальной стек сервисов платформы:
docker compose up -d
Критический этап валидации — сверка состояния метаданных хранилища. Ошибки рассинхронизации возникают, если бинарные файлы в S3-бакете не соответствуют записям в служебной таблице storage.objects:
-- Проверка наличия «осиротевших» записей в БД без физических файлов
SELECT id, bucket_id, name, created_at
FROM storage.objects
WHERE id NOT IN (SELECT unnest(ARRAY['verified-file-uuid-1', 'verified-file-uuid-2']::text[]))
LIMIT 10;
-- Валидация прав доступа и схем авторизации
SELECT schema_name FROM information_schema.schemata
WHERE schema_name IN ('auth', 'storage', 'extensions', 'realtime');
После старта контейнеров выполняется сквозной healthcheck API-шлюза Kong и генерация тестового сессионного токена для подтверждения работоспособности GoTrue (Auth service):
# Валидация статуса Kong API Gateway
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/rest/v1/
# Проверка эндпоинта аутентификации
curl -s -X POST 'http://127.0.0.1:8000/auth/v1/token?grant_type=password' \
-H "apikey: ${ANON_KEY}" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"correct_password"}'
Для минимизации простоя при аварийном переключении внешний трафик перенаправляется на чистый статический IPv4-адрес нового сервера через изменение DNS A-записи с TTL = 60 секунд либо путем перемещения плавающего IP (Floating IP). Конечный RTO при соблюдении регламента на KVM VPS с быстрыми накопителями NVMe и широким каналом составляет менее 15 минут, а сквозное версионирование WAL сохраняет показатель RPO на уровне фактических секунд до аварии.
Экономика и архитектура: Supabase Cloud vs Firebase vs Self-Hosted KVM VPS
Линейный рост базы пользователей неизбежно переводит архитектурную дискуссию из плоскости удобства прототипирования в плоскость совокупной стоимости владения (TCO, Total Cost of Ownership) и предсказуемости задержек ядра базы данных. Проприетарные бессерверные платформы (BaaS) выставляют счета на основе квантования микроопераций — объема переданных данных, количества операций ввода-вывода или отдельных чтений документов. В результате финансовая модель проекта становится заложницей неоптимальных клиентских запросов и неконтролируемого роста сетевого трафика.
┌─────────────────────────────────────────────────────────────────────────┐
│ СРАВНЕНИЕ АРХИТЕКТУРНЫХ ПОДХОДОВ │
├──────────────────────┬──────────────────────┬───────────────────────────┤
│ Google Firebase │ Supabase Cloud │ Self-Hosted на KVM VPS │
│ (NoSQL Firestore) │ (Managed SaaS) │ (tropic.host) │
├──────────────────────┼──────────────────────┼───────────────────────────┤
│ • Оплата за операции │ • Оплата за ресурсы │ • Фиксированная цена ноды │
│ чтения/записи │ + скрытый Egress │ • Трафик без наценок │
│ • Жесткий Lock-in │ • Вытеснение пула │ • Гарантия vCPU (%st=0.0) │
│ • NoSQL денормал. │ соединений │ • NVMe PCIe 4.0 4K QD1 │
│ • Непредсказуемый │ • CPU Throttling │ • Полный root/sysctl │
│ OpEx при росте │ на базовых тарифах │ • Независимость данных │
└──────────────────────┴──────────────────────┴───────────────────────────┘
Анатомия скрытых расходов: Firebase vs Supabase
При прямом сопоставлении Firebase vs Supabase разница кроется в фундаментальной модели монетизации и структуре хранения данных:
- Биллинг операций в Google Firebase (Cloud Firestore):
- Тарификация строится на атомарных событиях: $0.06 за 100 000 операций записи и $0.18 за 100 000 операций чтения.
- Отсутствие реляционных связей (JOIN) вынуждает денормализовать структуры. Одно обновление профиля пользователя с каскадной синхронизацией по связанным коллекциям генерирует сотни скрытых операций
DocumentReference.set()илиbatch.commit(). - Ошибка в клиентском коде (бесконечный цикл в
onSnapshot()-листере или реактивном хуке) способна за считаные часы исчерпать суточный бюджет и сгенерировать внезапный счет на тысячи долларов. - Дополнительно взимается плата за исходящий egress traffic по расценкам Google Cloud Network Tier ($0.12 за 1 ГБ данных, отдаваемых в публичный интернет).
- Лимиты и мультиарендность Supabase Cloud:
- Управляемый облачный Supabase формально предоставляет фиксированные тарифные планы (Free, Pro от $25/мес, Team от $599/мес), однако реальная инфраструктура жестко ограничена квотами на vCPU и объем оперативной памяти виртуальных машин AWS.
- На тарифе Pro дисковое пространство свыше базовых 8 ГБ тарифицируется по $0.125 за ГБ, а egress traffic сверх включенных 250 ГБ стоит $0.09 за ГБ. Нагруженный медиа-сервис или активный обмен по WebSocket через Realtime Engine генерирует 5–10 ТБ исходящих данных в месяц, что добавляет к базовому тарифу еще $450–$900 ежемесячно исключительно за счет сетевого интерфейса.
- Пул соединений к PostgreSQL на общих облачных инстансах упирается в системные лимиты памяти. При превышении порога соединений пулер Supavisor начинает сбрасывать входящие транзакции с ошибкой
503 Service Unavailable, вынуждая переходить на выделенные Compute Add-ons стоимостью от $110 до $1 000+ в месяц.
Развертывание Supabase на VPS под собственным управлением полностью нивелирует искусственные ограничения биллинга. Аренда изолированного инстанса устраняет метрику «стоимость одного SQL-запроса» — серверная емкость ограничена исключительно физическими характеристиками вычислительного узла и дисковой подсистемы.
Техническое сравнение платформ
В таблице сопоставлены ключевые архитектурные и экономические параметры проприетарных облачных платформ и собственного изолированного KVM-сервера:
| Архитектурный критерий | Google Firebase (Firestore) | Supabase Cloud (Pro / Team) | Self-Hosted Supabase на KVM VPS (tropic.host) |
|---|---|---|---|
| Модель затрат (Cost Model) | Pay-per-operation (чтение, запись, удаление документов) + Egress | Базовая подписка ($25–$599/мес) + Compute Add-ons + Egress | Фиксированная аренда KVM-ноды (без скрытых счетов и без наценок за объем данных) |
| Стоимость Egress-трафика | $0.12 / ГБ (после 10 ГБ/мес) | $0.09 / ГБ (после 250 ГБ/мес) | Включен в тариф ноды (симметричный порт 1–10 Гбит/с, TCP BBR) |
| Вычислительные ресурсы | Абстрактные Cloud Functions (Cold starts до 1.5–3 сек) | Shared vCPU на базовых планах; CPU throttling при пиках | Выделенные vCPU AMD EPYC / Ryzen 9 / Xeon (%st = 0.0% гарантированно) |
| Дисковая подсистема (IOPS) | Ограничена квотами Firestore (1 запись в секунду на документ) | Лимиты EBS-томов AWS (3 000 IOPS базово, апгрейд за плату) | Корпоративные NVMe PCIe 4.0 (>50 000 IOPS на 4K QD1, прямой доступ) |
| Модель данных и запросы | NoSQL, документная; отсутствие агрегаций, нет JOIN | Полноценный PostgreSQL 15/16/17 (с расширениями pgvector, PostGIS) |
Полноценный PostgreSQL под полным root-контролем, тюнинг sysctl и postgresql.conf |
| Лимиты соединений (Connections) | Ограничены лимитами одновременных подключений SDK | Ограничены пулером Supavisor в зависимости от тарифа Compute | До 10 000+ соединений (тюнинг PgBouncer, max_connections, work_mem) |
| Риск Vendor Lock-in | Критический (проприетарный SDK, миграция требует переписывания бэкенда) | Средний (экспорт в стандартный SQL возможен, но завязан на сервисы) | Нулевой (стандартные OCI-образы Docker Compose, чистый pg_dump без зависимостей) |
| Суверенитет данных (GDPR/152-ФЗ) | Серверы за пределами прямого контроля, зависимость от юрисдикции Google | Зависимость от доступности регионов AWS; ограничения по локализации | Полный суверенитет, локализация в ЕС (Франкфурт, Амстердам) или Турции (Стамбул), шифрование LUKS |
| Расчет TCO при базе 200 ГБ и трафике 8 ТБ/мес | ~$1 200 – $1 800 / мес (зависит от интенсивности операций) | ~$790 – $1 100 / мес (Pro + Compute 4XL + превышение диска и Egress) | ~$35 – $70 / мес (фиксированная цена ноды на tropic.host с NVMe) |
Детерминированный TCO и производительность KVM VPS
Развертывание собственного стека выступает безальтернативным решением при проектировании систем с высоким фактором Information Gain и тяжелыми транзакционными нагрузками. Выбирая KVM-сервер как технологическую основу, инженер получает детерминированную среду:
- Гарантированная изоляция процессора:
В управляемых облаках многопользовательская среда приводит к «шумным соседям» (noisy neighbors), что выражается в росте системной метрикиCPU Steal Time(%st). При росте%stсвыше 2–5% время отклика планировщика PostgreSQL на выполнение запросов деградирует в десятки раз. Архитектурный эталон KVM-нод платформы tropic.host гарантирует честное аппаратное квантование ресурсов:bash # Мониторинг системного воровства процессорных тактов на KVM-ноде vmstat 1 5 | awk '{print "usr:" $13 " sys:" $14 " idl:" $15 " wai:" $16 " st:" $17}'Значениеst:0подтверждает, что физические такты ядра (AMD EPYC с частотой 3.5+ ГГц или Ryzen 9 до 5.7 ГГц) полностью принадлежат изолированному гипервизору без оверселлинга. - Утилизация шины NVMe PCIe 4.0 без искусственных троттлингов:
Облачные СУБД жестко лимитируют Burst IOPS. Запись транзакционного журнала (WAL) в PostgreSQL требует синхронных сбросов буферов через системный вызовfdatasync(). Если дисковая подсистема облачного провайдера искусственно ограничивает задержку записи на уровне 5–10 мс, параметр задержки коммита транзакции (commit latency p99) мгновенно парализует производительность PostgREST. Использование локальных серверных накопителей NVMe PCIe 4.0 корпоративного класса (со случайным чтением блоками 4K QD1 свыше 50 000 IOPS) обеспечивает latency на запись WAL в пределах сотен микросекунд. - Сетевой стек и отсутствие биллинга Egress Traffic:
Растущий медийный трафик (S3 Storage через MinIO/Supabase Storage) и аналитические вебхуки в облачной инфраструктуре тарифицируются отдельно за каждый гигабайт. При развертывании Supabase на VPS в таких локациях, как Франкфурт (Equinix FR2) или Амстердам (NIKHEF) на инфраструктуре tropic.host, стек подключается к симметричным аплинкам пропускной способностью 1–10 Гбит/с с прямой BGP-маршрутизацией. Активация алгоритма управления перегрузками TCP BBR на уровне ядра Linux нивелирует потери пакетов на длинных сетевых маршрутах:bash # Проверка и применение алгоритма BBR для высоконагруженных сокетов Kong и PostgREST sysctl -w net.core.default_qdisc=fq sysctl -w net.ipv4.tcp_congestion_control=bbr
Юридический суверенитет и защита от Vendor Lock-in
Использование Firebase делает проект архитектурным заложником экосистемы Google. Клиентский код глубоко пронизывается вызовами проприетарных SDK (@firebase/firestore, @firebase/auth). Попытка сменить стек в будущем потребует полного переписывания слоя взаимодействия с данными, миграции нестандартизированных JSON-документов и рефакторинга всей системы безопасности.
Стек Supabase на базе стандартного открытого ПО функционирует через открытые протоколы: * Аутентификация: стандартизированные токены JWT (RFC 7519) и сессии OAuth 2.0. * Доступ к данным: стандартный протокол PostgreSQL по TCP-порту 5432, REST API через спецификацию OpenAPI (PostgREST), Realtime-обмен через WebSocket (Phoenix Channels). * Безопасность: декларативные политики на уровне строк (Row Level Security, RLS), исполняемые непосредственно ядром СУБД, а не закрытыми правилами firestore.rules.
Такая архитектура исключает vendor lock-in: в любой момент данные и схемы экспортируются стандартной утилитой pg_dump, а контейнеры переносятся на любой другой сервер за время, необходимое для восстановления архива.
Дополнительный фактор — соответствие локальным законам о защите персональных данных (GDPR в Европе, 152-ФЗ в РФ, KVKK в Турции). Развертывание базы данных на собственном KVM-сервере позволяет контролировать точное физическое местоположение накопителя, шифровать блочные устройства с помощью LUKS с закрытыми ключами, недоступными третьим лицам, и изолировать сетевой контур приватными VLAN или WireGuard-туннелями. Для международных команд критична также финансовая независимость: инфраструктура tropic.host поддерживает прямую оплату криптовалютами (USDT TRC20/TON, BTC) и международными банковскими картами без блокировок и посреднических комиссий, гарантируя бесперебойность продакшн-окружения независимо от внешних регуляторных рисков.
Таким образом, собственная альтернатива Firebase на своем сервере решает фундаментальные проблемы инженерной инфраструктуры: фиксирует TCO на минимальном уровне, гарантирует аппаратную производительность дисков и CPU без скрытых лимитов, защищает проект от навязанных тарифов за egress traffic и сохраняет за владельцем 100% контроль над кодом, базой данных и правами доступа.
Часто задаваемые вопросы (FAQ)
Сколько ресурсов VPS требуется для комфортной работы self-hosted Supabase?
Для стабильной работы всех 12+ микросервисов стека требуется минимум 2 vCPU и 4 ГБ оперативной памяти. Для production-проектов с активным использованием Realtime и векторного поиска pgvector рекомендуется конфигурация от 4 vCPU, 8-16 ГБ RAM на базе KVM с серверными NVMe-накопителями.
Можно ли развернуть Supabase на контейнерной виртуализации OpenVZ или LXC?
Крайне не рекомендуется. Стек Supabase включает интенсивную работу PostgreSQL с дисковой подсистемой, сетевые сокеты Realtime и специфические системные вызовы ядра. Требуется чистая аппаратная виртуализация KVM с честным выделением ресурсов и нулевым CPU Steal Time.
Как безопасно изолировать панель Supabase Studio от публичного интернета?
Для защиты веб-панели рекомендуется не открывать порт Studio наружу, а настроить доступ через обратный прокси Nginx с ограничением по IP-адресам (allow/deny), включить базовую HTTP-аутентификацию (htpasswd) либо пробрасывать защищенный SSH-туннель.
Поддерживает ли self-hosted версия векторный поиск pgvector для AI-приложений?
Да, официальный образ PostgreSQL в составе Docker-дистрибутива Supabase поставляется с предустановленным расширением pgvector, что позволяет хранить эмбеддинги и выполнять векторный поиск HNSW прямо на собственном VPS без дополнительных затрат.
В чем главное преимущество self-hosted Supabase перед Firebase?
Self-hosted Supabase предоставляет полноценную реляционную СУБД PostgreSQL вместо проприетарной NoSQL-базы, исключает привязку к инфраструктуре Google, не тарифицирует каждую операцию чтения/записи и обходится в разы дешевле при высоких объемах трафика.