SupabasePostgresМиграция

Supabase в России: как оплатить или развернуть у себя

6 мин чтения

Supabase помогает быстро сделать бэкенд: база, вход пользователей, файлы. Из России с ним две проблемы: оплата и хранение данных. Ниже о том, как их решить.

Что не так с облаком Supabase из России

Оплата. Платные тарифы оплачиваются картой через Stripe. Карты российских банков не проходят. Остаются посредники, которые платят иностранной картой за комиссию. Это работает, но без гарантий: аккаунт оформлен на условиях, которые не предусматривают пользователей из России.

Данные. Облако Supabase размещается у AWS за пределами России. Закон 152-ФЗ требует, чтобы персональные данные граждан РФ при сборе записывались в базы на территории России. Для сервиса с регистрацией пользователей это прямое требование.

Варианты

  1. Облако через посредника. Ничего не меняется в коде, но остаются комиссия, риск и вопрос с данными.
  2. Self-hosted на своём сервере. Официальная сборка Supabase на Docker. Полный контроль, но обновления, бэкапы, SSL и мониторинг на своей стороне.
  3. Self-hosted у хостинг-провайдера. Та же сборка, эксплуатацию берёт на себя провайдер.

Код приложения во всех трёх вариантах почти не меняется: supabase-js работает с self-hosted так же, как с облаком.

Что входит в self-hosted Supabase

Официальная сборка состоит примерно из 13 контейнеров:

КомпонентЗадача
Postgresбаза с расширениями Supabase
PostgRESTREST API по таблицам
Auth (GoTrue)регистрация, вход, токены
Realtimeизменения таблиц, broadcast, presence
Storage + imgproxyфайлы и ресайз картинок
Edge Runtimeфункции на Deno
Supavisorпул соединений
postgres-metaAPI для Studio
Studioвеб-админка
API-шлюзединая точка входа (Kong или Envoy)
Logflare + Vectorлоги и аналитика

Рекомендация для self-hosted от 4 GB памяти. На сервере с 2 GB Supabase вместе с приложением не поместится.

Чем self-hosted отличается от облака

  • Нет branching, Management API и supabase link. Studio показывает один проект.
  • Edge Functions кладутся файлами в каталог функций, команды supabase functions deploy нет.
  • Письма (подтверждение, magic link, сброс пароля) уходят через свой SMTP. Без него регистрация с подтверждением почты не работает.
  • Ключи. anon и service_role выпускаются из своего JWT-секрета. Секрет нужен и собственному бэкенду, чтобы проверять токены пользователей.
  • Обновления и бэкапы не происходят сами. Версию компонентов обновляет владелец сервера, бэкапы базы и файлов Storage настраиваются отдельно.

Перенос с supabase.com

Официальный способ переноса базы использует Supabase CLI. Строка подключения к старой базе берётся в настройках проекта.

# роли, схема и данные из старого проекта
supabase db dump --db-url "$OLD_DB_URL" -f roles.sql --role-only
supabase db dump --db-url "$OLD_DB_URL" -f schema.sql
supabase db dump --db-url "$OLD_DB_URL" -f data.sql --use-copy --data-only

# восстановление в новую базу
psql --single-transaction --variable ON_ERROR_STOP=1 \
  --file roles.sql \
  --file schema.sql \
  --command 'SET session_replication_role = replica' \
  --file data.sql \
  --dbname "$NEW_DB_URL"

session_replication_role = replica отключает триггеры на время загрузки, чтобы данные не обрабатывались повторно.

Что ещё учесть:

  • Файлы Storage в дамп не попадают. Их переносят отдельно: скриптом через Storage API или по S3-протоколу, если он включён на обеих сторонах.
  • Пользователям придётся войти заново. Токены подписаны старым JWT-секретом, новый экземпляр их не примет.
  • Пользователи и хеши паролей лежат в таблице auth.users. Если она попала в дамп данных, повторная регистрация не нужна. Проверка: число строк в auth.users до и после переноса.
  • Ключи в приложении меняются на новые anon и service_role, адрес проекта тоже.
  • Настройки Auth (redirect URL, провайдеры OAuth, шаблоны писем) переносятся вручную.

Безопасность после переезда

Главная ошибка в Supabase не связана с хостингом: таблица без политик RLS доступна всем, у кого есть ключ anon, а он лежит в коде фронтенда. После переноса стоит проверить каждую таблицу в схеме public:

select tablename
from pg_tables
where schemaname = 'public' and not rowsecurity;

Каждая таблица из этого списка открыта для чтения и записи через API. Для неё нужно включить RLS и описать политики.

Ключ service_role обходит RLS и никогда не попадает во фронтенд, только в серверный код.

Читать дальше