Skip to content

Self-Hosting

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

    Terminal window
    bun install
  2. Start a Convex dev deployment:

    Terminal window
    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.

  3. Configure essential secrets.

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

    Terminal window
    # 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_...
  4. 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.

  5. Start the stack:

    Terminal window
    bun run dev
  1. Update SITE_URL in Convex to your public domain (e.g., https://app.yourdomain.com).

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

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

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

  5. Build and start the production stack:

    Terminal window
    bun run build
    bun run start

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

Terminal window
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
Terminal window
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)

Section titled “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):

Terminal window
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

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.

Terminal window
VITE_WEB_URL=https://app.yourdomain.com # Defaults to https://app.teakvault.com
Terminal window
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.

  • 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.