Supabase помогает быстро сделать бэкенд: база, вход пользователей, файлы. Из России с ним две проблемы: оплата и хранение данных. Ниже о том, как их решить.
Что не так с облаком Supabase из России
Оплата. Платные тарифы оплачиваются картой через Stripe. Карты российских банков не проходят. Остаются посредники, которые платят иностранной картой за комиссию. Это работает, но без гарантий: аккаунт оформлен на условиях, которые не предусматривают пользователей из России.
Данные. Облако Supabase размещается у AWS за пределами России. Закон 152-ФЗ требует, чтобы персональные данные граждан РФ при сборе записывались в базы на территории России. Для сервиса с регистрацией пользователей это прямое требование.
Варианты
- Облако через посредника. Ничего не меняется в коде, но остаются комиссия, риск и вопрос с данными.
- Self-hosted на своём сервере. Официальная сборка Supabase на Docker. Полный контроль, но обновления, бэкапы, SSL и мониторинг на своей стороне.
- Self-hosted у хостинг-провайдера. Та же сборка, эксплуатацию берёт на себя провайдер.
Код приложения во всех трёх вариантах почти не меняется: supabase-js работает с self-hosted так же, как с облаком.
Что входит в self-hosted Supabase
Официальная сборка состоит примерно из 13 контейнеров:
| Компонент | Задача |
|---|---|
| Postgres | база с расширениями Supabase |
| PostgREST | REST API по таблицам |
| Auth (GoTrue) | регистрация, вход, токены |
| Realtime | изменения таблиц, broadcast, presence |
| Storage + imgproxy | файлы и ресайз картинок |
| Edge Runtime | функции на Deno |
| Supavisor | пул соединений |
| postgres-meta | API для 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 и никогда не попадает во фронтенд, только в серверный код.