Run Flagon
Flagon is source-available and self-hostable. Self-hosting runs exactly the same code as the managed service: three apps plus a Postgres database.
apps/
web/ marketing site + docs (optional to run)
app/ the console → sign in, manage flags
api/ the control plane → OFREP evaluation + /v1 managementThe console and API are the two you need; everything talks to Postgres through the API.
Prerequisites
- Node.js 22 or newer.
- PostgreSQL 17. Managed (Neon, RDS, Cloud SQL) or your own.
- Docker (optional) if you want to run Postgres locally with the bundled compose file.
1. Clone and install
git clone https://github.com/flagon-io/flagon.git
cd flagon
npm install2. Start a database
For local development, the repo ships a Postgres service:
npm run compose:up # postgres on localhost:5432 (user/pass/db: flagon)In production, point the apps at your managed Postgres instead (see the production notes below).
3. Configure the environment
Each app reads its own env file. Copy the examples and fill them in:
cp apps/api/.env.example apps/api/.env
cp apps/app/.env.example apps/app/.env.localThe essentials:
| Variable | App | What it is |
| --- | --- | --- |
| DATABASE_URL | api, app | Postgres connection string. |
| BETTER_AUTH_SECRET | app | A long random secret that signs sessions. Generate one. |
| NEXT_PUBLIC_API_URL | app | Where the API is reachable. |
| NEXT_PUBLIC_APP_URL · APP_URL | app · api | The console's public URL (also used for CORS). |
Generate the auth secret with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"The example ships BETTER_AUTH_SECRET=dev-secret-change-me. A production build
refuses to start with that placeholder. Set a real, random secret, and keep it
stable, rotating it signs everyone out.
4. Run the migrations
The API and the console each own a migration pipeline. Apply both:
npm run db:migrate -w @flagon/api
npm run db:migrate -w @flagon/appMigrations are forward-only and safe to run on every deploy; they no-op when there is nothing new.
5. Start the apps
For local development, run everything at once:
npm run dev # web :3000 · app :3001 · api :3002For production, build and start each app you need:
npm run build
npm run start -w @flagon/api
npm run start -w @flagon/appOpen the console, create your organization, and follow the Quickstart.
Production notes
A few settings matter once real users are involved:
-
Run as the restricted database role. Flagon isolates every tenant's data with Postgres row-level security, and RLS is only enforced when the API connects as a non-owner role. Create a
flagon_approle withNOBYPASSRLS, grant it table access, and set its pooled connection string asAPP_DATABASE_URL. The API prefers it overDATABASE_URLat runtime, so queries run under RLS. Migrations still use the owner connection (DATABASE_URL_UNPOOLED).This is the one that mattersIf the API connects as the database owner or a superuser, RLS is silently bypassed and organizations can see each other's flags. Verify the runtime role before going live.
-
Share the session across subdomains. Serving the console, API, and site on subdomains of one apex? Set
AUTH_COOKIE_DOMAIN=.your-domainso the session cookie is shared. -
Wire up email (optional). Set
RESEND_API_KEYandEMAIL_FROMto send real invites and verification mail. Without a key, emails print to the server log, which is fine for a trial. -
Turn on error tracking (optional). Set
SENTRY_DSN(API) andNEXT_PUBLIC_SENTRY_DSN(console). Both are inert until set.
Next
- Quickstart: create your first flag.
- SDK keys: connect an app to your instance.