Self-host docs

Run Flowstace locally with Docker and keep the OSS path intact.

This setup boots PostgreSQL and the Next.js app locally. AI and Stripe are optional. The product works as a self-hosted agency workspace without either integration.

Quick start

1. Prepare env

Copy `.env.example`, set the database URL, Better Auth values, and choose whether AI, email delivery, or Stripe should stay enabled.

2. Start Docker

Bring up Postgres and the Next.js app with `docker compose up --build`. The web container installs deps, pushes the schema, and starts dev mode automatically.

3. Create the first org

Open the app, sign up, and complete onboarding. For self-hosted OSS use, choose the `OSS` plan in onboarding.

4. Optional SaaS config

If you later want hosted billing behavior, add Stripe price IDs and webhook secret, then expose `/api/billing/webhooks/stripe` publicly.

5. Optional automation cron

Set `AGENCYOS_AUTOMATION_SECRET` and call the daily and weekly digest endpoints from cron. This keeps email digests available without adding a separate worker yet.

Commands

cp .env.example .env
docker compose up --build

# optional, outside Docker
npm install
npm run db:push
npm run dev:web

# optional daily digest cron
curl -X POST http://localhost:3000/api/automation/digests/daily \
  -H "Authorization: Bearer $AGENCYOS_AUTOMATION_SECRET"

# optional weekly digest cron
curl -X POST http://localhost:3000/api/automation/digests/weekly \
  -H "Authorization: Bearer $AGENCYOS_AUTOMATION_SECRET"

Environment

DATABASE_URL

PostgreSQL connection string for Prisma and Better Auth.

BETTER_AUTH_SECRET

Required for session signing.

BETTER_AUTH_URL

Public app URL, e.g. http://localhost:3000.

AGENCYOS_DEFAULT_PLAN

Default onboarding plan. Use `OSS` for self-host.

ANTHROPIC_API_KEY

Optional. Enables Claude-backed Szef mode.

AGENCYOS_ENABLE_AI_PREVIEW

Optional. Keeps preview AI mode available without Anthropic.

EMAIL_PROVIDER

Optional. Mail transport selector: `RESEND`, `SMTP`, `SES`, or leave empty to auto-detect / fallback.

RESEND_API_KEY

Optional. Enables live delivery for email 2FA and future notification emails.

EMAIL_FROM_ADDRESS

Optional with a live mail provider. Sender address for security codes and future notifications.

SMTP_HOST

Optional for SMTP delivery. Mail server hostname.

SMTP_PORT

Optional for SMTP delivery. Mail server port.

SMTP_SECURE

Optional for SMTP delivery. Set to true for implicit TLS.

SMTP_USERNAME

Optional for SMTP delivery. Mail server username.

SMTP_PASSWORD

Optional for SMTP delivery. Mail server password.

SES_REGION

Optional for AWS SES. Region used by the SES client.

SES_ACCESS_KEY_ID

Optional for AWS SES. Access key ID for live transactional delivery.

SES_SECRET_ACCESS_KEY

Optional for AWS SES. Secret access key for live transactional delivery.

MAILERLITE_ENABLED

Optional. Enables public newsletter capture on the landing page when set to true.

MAILERLITE_API_KEY

Optional. MailerLite API key for sending landing newsletter leads to your audience.

MAILERLITE_GROUP_ID

Optional. MailerLite group ID that receives new Flowstace landing signups.

AGENCYOS_AUTOMATION_SECRET

Optional but recommended for cron-triggered automation endpoints like daily and weekly digests.

AGENCYOS_STORAGE_ROOT

Optional but recommended for VPS/SaaS. Persistent writable path for uploads, logos, and avatars.

STRIPE_SECRET_KEY

Optional. Only needed if you want live billing and webhooks.

Operational notes

  • Every data query is organization-scoped. The first onboarding run creates the first tenant membership.
  • Choose `OSS` during onboarding if you want AI features locked by default.
  • Stripe billing is optional for self-host. Without it, Billing renders safely but checkout stays unavailable.
  • Email 2FA on paid plans works with Resend, or falls back to local capture/logging in development when no mail provider is configured.
  • Daily and weekly digests can be triggered by cron through `/api/automation/digests/daily` and `/api/automation/digests/weekly` with the automation bearer secret.
  • If Prisma schema changes while Docker is already running, rerun `docker compose exec -T web npm run db:push` and restart `web`.