Skip to content
Teak
Esc
navigateopen⌘Jpreview
On this page

Self-Hosting

Self-hosting gives you full control over your data and billing while matching the hosted experience.

What you’ll need

  • Convex CLI (npm i -g convex)
  • Access to secrets for the features you want: Groq (AI), Kernel (screenshots), Resend (email), Polar (billing)

Quickstart (local)

Clone and install

Clone the repo and install dependencies:

bun install

Start a Convex dev deployment

bunx convex dev

This creates a dev deployment and prints the CONVEX_SITE_URL and CONVEX_URL. It does not configure Better Auth — that’s the next step.

Configure essential secrets

Run these commands to set the minimum required secrets in your Convex dashboard:

# Security & Auth
npx convex env set BETTER_AUTH_SECRET $(openssl rand -base64 32)
npx convex env set SITE_URL http://app.teak.localhost:1355

# Optional: AI (if you want card processing)
npx convex env set GROQ_API_KEY gsk_...

Create local env files

Copy the Convex URLs from your dashboard into each app’s .env.local. Each app uses a framework-specific prefix for the same two vars:

App Prefix
apps/web NEXT_PUBLIC_
apps/mobile EXPO_PUBLIC_
apps/extension, apps/desktop VITE_PUBLIC_

See Detailed Environment Reference for the full variable list.

Start the stack

bun run dev

Production basics

Update SITE_URL

Update SITE_URL in Convex to your public domain (e.g., https://app.yourdomain.com).

Point clients at production

Update CONVEX_SITE_URL and CONVEX_URL in your client env files to point to your production deployment.

Host the web app

Point your domain’s SITE_URL to wherever you are hosting the Next.js app.

Add optional services

Add email (RESEND_API_KEY) and billing (Polar) keys to Convex env if needed.

Build and start

bun run build
bun run start

Detailed Environment Reference

Add these to your env files before running locally or deploying.

Backend (packages/convex/.env.local)

SITE_URL=http://app.teak.localhost:1355
BETTER_AUTH_SECRET=your-secret               # Better Auth security
R2_ACCESS_KEY_ID=access-key                  # R2 S3 access key
R2_SECRET_ACCESS_KEY=secret-key              # R2 S3 secret key
R2_ENDPOINT=https://account.r2.cloudflarestorage.com
R2_BUCKET=teak-files                         # R2 bucket for private assets
KERNEL_API_KEY=token                         # Kernel Browser
GROQ_API_KEY=gsk_...                         # AI processing
POLAR_ACCESS_TOKEN=token                     # Billing
POLAR_ORGANIZATION_TOKEN=token               # Polar organization
POLAR_SERVER=sandbox                         # sandbox|production
POLAR_WEBHOOK_SECRET=secret                  # Polar webhooks
RESEND_API_KEY=token                         # Email service

Web (apps/web/.env.local)

CONVEX_DEPLOY_KEY=
NEXT_PUBLIC_CONVEX_URL=https://deployment.convex.cloud
NEXT_PUBLIC_CONVEX_SITE_URL=https://deployment.convex.site
TEAK_DEV_APP_URL=http://app.teak.localhost:1355   # Optional local override
# Origin your R2 files are served from, so the Content-Security-Policy allows
# loading images and documents. Set this to your bucket's public/signed-URL
# origin (e.g. https://your-bucket.<account>.r2.cloudflarestorage.com).
NEXT_PUBLIC_R2_STORAGE_ORIGIN=https://your-bucket.account.r2.cloudflarestorage.com

Client Apps (apps/mobile, apps/extension, apps/desktop)

Mobile, Extension, and Desktop share the same base variables (use EXPO_PUBLIC_ prefix for mobile, VITE_PUBLIC_ for extension and desktop):

VITE_PUBLIC_CONVEX_URL=https://deployment.convex.cloud
VITE_PUBLIC_CONVEX_SITE_URL=https://deployment.convex.site
TEAK_DEV_APP_URL=http://app.teak.localhost:1355   # Optional local override

Desktop-only

The desktop app additionally reads VITE_WEB_URL to know where to send sign-in and account links. Mobile and the extension do not use this variable.

VITE_WEB_URL=https://app.yourdomain.com   # Defaults to https://app.teakvault.com

Public API and MCP

PUBLIC_API_URL=https://yourdomain.com/api       # Optional: public API origin used in discovery
PUBLIC_MCP_URL=https://yourdomain.com/mcp       # Optional: defaults to PUBLIC_API_URL + /mcp
AUTH_ISSUER_URL=https://app.yourdomain.com      # Optional: OAuth issuer override for MCP discovery
TEAK_DEV_API_URL=https://deployment.convex.site # Optional local override

Convex serves the REST API at /api/v1, the MCP endpoint at /mcp, plus /healthz, /openapi.json, and OAuth protected-resource metadata. In production, Teak exposes these through apex path rewrites (e.g. https://teakvault.com/api and https://teakvault.com/mcp). For self-hosted setups, configure your reverse proxy or DNS to route /api and /mcp to the Convex deployment’s .convex.site domain.

Where to get the values

  • Convex URLs: Run bunx convex dev. It prints both CONVEX_URL (for the client) and CONVEX_SITE_URL (for the site/auth endpoint). You can also find these in the Convex Dashboard under “Settings” -> “Deployment”.
  • Better Auth:
    • BETTER_AUTH_SECRET: Generate a random string (e.g., via openssl rand -base64 32).
    • SITE_URL: This is the URL where your Next.js app is running. Locally, it’s http://app.teak.localhost:1355.
  • Optional Features:
    • R2_*: Create a private Cloudflare R2 bucket and an API token/S3 credentials with object read, write, and delete access.
    • GROQ_API_KEY: Get from Groq Console for AI-powered card processing.
    • KERNEL_API_KEY: Get from Kernel for automated link screenshots.
    • RESEND_API_KEY: Get from Resend for email verification and password resets.
    • POLAR_*: Get from Polar if you want to use the built-in billing system.

Last updated on July 31, 2026

Was this page helpful?