Self-hosting.
FeedbackFlow ships as a Docker image and runs against your own MongoDB. Your feedback, uploads, and tenant data stay on infrastructure you control.
Requirements
- Node.js 20+ (for local development) or Docker (recommended for deployment).
- MongoDB 7+ — managed (Atlas) or self-run.
- A domain with HTTPS for production.
Docker Compose
The fastest path. Compose brings up the app and a MongoDB instance together:
# 1 · Clone and configure
git clone <your-repo> && cd feedback
cp .env.example .env
# 2 · Generate an auth secret → paste into .env
openssl rand -base64 32
# 3 · Start everything
docker-compose up -d
# App is now on http://localhost:3000Environment variables
Configure the app through .env. The essentials:
| Variable | Required | Description |
|---|---|---|
MONGODB_URI | Yes | MongoDB connection string. |
BETTER_AUTH_SECRET | Yes | Auth signing secret (64+ chars). |
BETTER_AUTH_URL | Yes | The app's public URL. |
STORAGE_PROVIDER | No | local · s3 · r2 (default local). |
PLATFORM_ADMIN_EMAILS | For /admin | Comma-separated emails allowed into platform admin. |
CRON_SECRET | Prod | Bearer secret for the SLA-check job. |
BETTER_AUTH_SECRET and restrict PLATFORM_ADMIN_EMAILS to trusted accounts before going to production.Storage providers
Attachments can live wherever you choose. The storage layer is pluggable:
- local — files on the app's disk under
public/uploads. Good for a single node. - s3 — Amazon S3 or any S3-compatible bucket.
- r2 — Cloudflare R2.
Switch by setting STORAGE_PROVIDER and the provider's credentials in .env.
Database & indexes
Indexes are created automatically on first run. To initialise them explicitly:
npm run db:initTenant isolation is enforced through compound indexes keyed on tenantId, so queries never cross workspace boundaries.
Building the widget
The embed widget is a separate Vite build, output as a UMD bundle served from public/widget/widget.js:
npm run widget:build # production bundle
npm run widget:dev # watch modeHealth & jobs
A public health endpoint lets your orchestrator probe the app:
SLA evaluation runs as a cron-triggered job. Schedule a periodic call (authenticated with CRON_SECRET in production):
Production checklist
- Set a strong
BETTER_AUTH_SECRETand enable HTTPS. - Restrict
PLATFORM_ADMIN_EMAILSto trusted accounts. - Enable MongoDB authentication and automatic backups.
- Configure CORS for your domains.
- Schedule the SLA-check job and set
CRON_SECRET.