Formbricks на сервере: частые ошибки и решения
Formbricks — self-hosted платформа для форм и опросов с логикой ветвления, условными переходами и встраиванием в продукт: разумная альтернатива Typeform или Tally для тех, кто не хочет отдавать данные респондентов на сторонний SaaS. Разворачивается он через Docker Compose и в целом ставится за 10 минут — но именно из-за большого количества переменных окружения (шифрование, аутентификация, почта, домен) новички регулярно упираются в одни и те же ошибки. Ниже — разбор самых частых проблем и как их закрыть.
Содержание
- Как разворачивают Formbricks: Docker Compose и переменные окружения
- Контейнер падает или не стартует: NEXTAUTH_SECRET, ENCRYPTION_KEY, WEBAPP_URL
- Ошибки подключения к PostgreSQL и миграций
- SSL, reverse proxy и редирект-луп за Traefik/Nginx
- Не приходят email-уведомления: настройка SMTP
- Обновление, бэкапы и нехватка памяти
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Как разворачивают Formbricks: Docker Compose и переменные окружения
Официальный способ — Docker Compose. Минимальный набор сервисов: сам formbricks (Next.js-приложение) и postgres для хранения данных. Базовый файл выглядит примерно так:
services:
formbricks:
image: formbricks/formbricks:latest
restart: always
depends_on:
- postgres
ports:
- "3000:3000"
environment:
WEBAPP_URL: "https://forms.example.com"
NEXTAUTH_URL: "https://forms.example.com"
NEXTAUTH_SECRET: "${NEXTAUTH_SECRET}"
ENCRYPTION_KEY: "${ENCRYPTION_KEY}"
CRON_SECRET: "${CRON_SECRET}"
DATABASE_URL: "postgresql://formbricks:${POSTGRES_PASSWORD}@postgres:5432/formbricks?schema=public"
volumes:
- uploads:/home/nextjs/apps/web/uploads/
postgres:
image: postgres:15-alpine
restart: always
environment:
POSTGRES_USER: formbricks
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_DB: formbricks
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
uploads:
postgres_data:
Секреты (NEXTAUTH_SECRET, ENCRYPTION_KEY, CRON_SECRET) генерируются командой:
openssl rand -hex 32
Их нужно ровно три, и все три — разные строки. Складывать их в .env рядом с docker-compose.yml удобнее, чем прописывать прямо в файле — так секреты не улетят в git при случайном коммите.
Перед проектом стоит поднять сервер с достаточным запасом памяти: на 1-2 активных формах хватит 2 ГБ ОЗУ, но Next.js в режиме сборки и Prisma-миграции при апдейтах любят прожорливые пики — с 4 ГБ живётся спокойнее. Подробнее о том, как вообще готовить сервер под продакшен-докер-стек, — в статье про Docker Compose в проде.
Контейнер падает или не стартует: NEXTAUTH_SECRET, ENCRYPTION_KEY, WEBAPP_URL
Самая частая причина, по которой formbricks контейнер уходит в restart loop сразу после docker compose up -d, — не заданные или пустые переменные шифрования и аутентификации. Приложение при старте проверяет их наличие и падает с понятной, но легко пропускаемой в логах ошибкой:
docker compose logs formbricks --tail=50
Смотрите на строки вида Error: ENCRYPTION_KEY is not set или NEXTAUTH_SECRET must be a 32-byte hex string. Типичные грабли:
- Забыли создать
.env-файл — Compose подставляет пустые значения вместо${NEXTAUTH_SECRET}, приложение падает на старте. - Секрет неправильной длины —
ENCRYPTION_KEYдолжен быть ровно 32 байта в hex (64 символа), сокращённая или скопированная с обрезкой строка не пройдёт валидацию. WEBAPP_URLне совпадает сNEXTAUTH_URL— Formbricks требует их синхронности, иначе auth-редиректы уходят не туда, а сессии не создаются даже без явного краша.- URL с завершающим слэшем —
https://forms.example.com/вместоhttps://forms.example.comиногда ломает построение внутренних ссылок в письмах и виджете.
После правки .env контейнер нужно не просто перезапустить, а пересоздать, чтобы переменные подхватились:
docker compose up -d --force-recreate formbricks
Если падение происходит не сразу, а через 10-20 секунд после старта — почти всегда это уже следующая проблема, с базой данных.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОшибки подключения к PostgreSQL и миграций
Formbricks использует Prisma для миграций схемы, и они выполняются автоматически при первом старте контейнера. Здесь ловят три типа ошибок:
ECONNREFUSED на порт 5432. Контейнер formbricks стартует быстрее, чем Postgres успевает поднять сокет. depends_on в Compose гарантирует только порядок запуска контейнеров, а не готовность сервиса внутри. Решение — health check на постгресе:
postgres:
# ...
healthcheck:
test: ["CMD-SHELL", "pg_isready -U formbricks"]
interval: 5s
timeout: 5s
retries: 10
formbricks:
depends_on:
postgres:
condition: service_healthy
Неверный DATABASE_URL. Частая опечатка — использовать localhost вместо имени сервиса postgres внутри строки подключения. Внутри Docker-сети контейнеры видят друг друга по имени сервиса, а не по localhost (это порт хоста, не контейнера). Проверить фактическое имя пользователя и БД, с которыми поднялся Postgres:
docker compose exec postgres psql -U formbricks -d formbricks -c "\conninfo"
Миграция зависла или упала посередине. Если под капотом уже была база от старой версии Formbricks и вы обновились на мажорную версию, миграция может требовать ручного вмешательства. Смотрите полный лог:
docker compose logs formbricks | grep -i prisma
и сверяйтесь с changelog конкретной версии на GitHub перед апдейтом — большие мажорные релизы (переход между схемами базы) иногда описывают отдельный порядок действий.
SSL, reverse proxy и редирект-луп за Traefik/Nginx
Formbricks сам по себе слушает на 3000 порту без TLS — шифрование навешивает внешний reverse proxy. Тут возникает классическая для Next.js-приложений проблема: ERR_TOO_MANY_REDIRECTS или бесконечный редирект на /auth/login.
Причина почти всегда одна — рассинхрон между тем, что видит браузер (https://forms.example.com), и тем, что думает о себе приложение. Если WEBAPP_URL/NEXTAUTH_URL указывают на http://, а прокси терминирует TLS и проксирует на 3000 порт по HTTP, NextAuth генерирует secure-cookie для https-контекста, но само приложение считает себя http — и куки, и редиректы начинают противоречить друг другу.
Что проверить:
WEBAPP_URLиNEXTAUTH_URL— строгоhttps://, без порта, без слэша в конце.- Прокси должен пробрасывать заголовки
X-Forwarded-Proto: httpsиX-Forwarded-Host, иначе Next.js не поймёт, что запрос пришёл по HTTPS.
Пример для Nginx:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Если используете Traefik, у него X-Forwarded-Proto проставляется автоматически при правильно настроенном entrypoint с TLS — но стоит явно проверить это в браузере через DevTools → Network → Headers на запросе к /api/auth/session. Разницу между Traefik и Nginx Proxy Manager для такого сценария разбирали в статье про выбор reverse proxy для сервера. Сам сертификат и его продление — отдельная больная тема, если раньше не настраивали автопродление, посмотрите разбор частых ошибок Let's Encrypt.
Не приходят email-уведомления: настройка SMTP
Formbricks отправляет письма — подтверждение регистрации, уведомления о новых ответах, приглашения в команду — через SMTP, который нужно настроить отдельно. Без него аккаунт можно создать, но письма верификации просто не придут, и часть функций (например, приглашение коллег) не заработает.
Переменные окружения для SMTP:
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE_ENABLED=0
SMTP_USER=noreply@example.com
SMTP_PASSWORD=your-password
MAIL_FROM=noreply@example.com
Частые ошибки:
- Порт 587 без
SMTP_SECURE_ENABLED— на 587 нужен STARTTLS, а не прямой TLS-коннект; если приложение пытается сразу шифровать соединение как на 465-м порту, будетECONNRESETили таймаут. - Провайдер блокирует внешний SMTP от VPS — некоторые почтовые сервисы (в том числе многие бесплатные ящики) режут отправку с новых IP или требуют отдельного разрешения "App Password" вместо обычного пароля от ящика.
- Нет обратного DNS (PTR) на IP сервера — письма уходят, но падают в спам или вовсе отклоняются принимающей стороной. Это отдельная настройка на уровне провайдера сервера, не Formbricks.
Если поднимаете почту с нуля именно под такие уведомления, проще и надёжнее не городить свой Postfix ради одного сервиса, а взять транзакционного провайдера (Resend, Postmark, SMTP от Яндекс 360 и т.п.) — так письма стабильнее долетают. Но если инфраструктура уже есть, логика настройки почтового сервера на VPS та же, что описана в статье про настройку Postfix.
Проверить SMTP можно и напрямую из контейнера, не дожидаясь реального действия в UI:
docker compose exec formbricks node -e "
const nodemailer = require('nodemailer');
const t = nodemailer.createTransport({host: process.env.SMTP_HOST, port: process.env.SMTP_PORT, auth: {user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD}});
t.verify().then(console.log).catch(console.error);
"
Обновление, бэкапы и нехватка памяти
Обновление. Тег latest в образе — не лучшая практика для продакшена: он может подтянуть мажорный релиз с изменением схемы базы без предупреждения. Разумнее закрепить конкретную версию (formbricks/formbricks:v3.x.x) и обновляться осознанно, читая release notes перед каждым шагом:
docker compose pull formbricks
docker compose up -d formbricks
Перед любым обновлением — снимок базы:
docker compose exec postgres pg_dump -U formbricks formbricks > formbricks_backup_$(date +%F).sql
Бэкапы volume'ов. Кроме базы, отдельного внимания требует volume с загруженными файлами (uploads) — картинки в вопросах, логотипы. Если он живёт только в Docker volume без внешнего бэкапа, потеря диска сервера означает потерю и базы, и всех вложений разом. Общий подход к бэкапу Docker-volume'ов на сервере разобран в статье про бэкап Docker volume.
Нехватка памяти при сборке/миграции. На серверах с 1-2 ГБ ОЗУ Next.js-приложение может уходить в OOM-kill именно в момент миграции или прогрева кэша после рестарта — в логах системы это видно как Out of memory: Killed process в dmesg или journalctl -k. Решения — либо увеличить объём сервера, либо временно добавить swap:
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
Swap не заменяет нормальную оперативку под нагрузкой, но снимает разовые пики при рестартах и обновлениях.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Formbricks можно развернуть без Docker?
Официально поддерживается только Docker/Docker Compose — это самый предсказуемый путь. Ручная установка Node.js-приложения с отдельным Postgres теоретически возможна, но вы теряете воспроизводимость окружения и усложняете себе апдейты.
Нужен ли Redis для self-hosted Formbricks?
В некоторых версиях Redis используется для rate limiting и кэша; если переменная подключения к Redis не задана, приложение в большинстве случаев просто отключает эту функциональность и работает без него — но для точного поведения конкретной версии сверяйтесь с её документацией на docs.formbricks.com.
Почему после обновления формы перестали открываться на встроенном виджете?
Проверьте, не изменился ли формат WEBAPP_URL или CORS-настройки между версиями — иногда мажорные релизы меняют домен, с которого разрешена встройка виджета на сторонние сайты.
Можно ли запустить несколько организаций (multi-tenant) на одном инстансе?
Да, Formbricks поддерживает несколько организаций и проектов в одной инсталляции — это не требует отдельных контейнеров, разграничение происходит на уровне приложения и базы.
Как перенести Formbricks на другой сервер?
Снять pg_dump базы, скопировать volume uploads, поднять тот же docker-compose.yml с теми же .env-секретами (особенно ENCRYPTION_KEY — без него зашифрованные в базе данные не расшифровать) на новом сервере и восстановить дамп.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →