meetbot / docs
Self-host

Self-host

Run the entire meetbot stack on your own infrastructure. Docker Compose for one-machine setups, Helm chart for Kubernetes. MIT-licensed; no metering loop, no phone-home.

We ship the same orchestrator + bot images that power meetbot.dev. Self-host is the path you pick when data residency, air-gapped networks, or bot-hour volume above ~1,000 hr/month make the hosted plan the wrong fit.

Three ways to run it

What's in the bundle

ServiceWhat it does
orchestratorHTTP API on :3010. Job dispatch, webhooks, admin.
orchestrator-workerpg-boss queue. Spawns bot containers per job.
postgresJob state, OAuth credentials, webhook delivery log.
caddyTLS-terminating reverse proxy. Auto Let's Encrypt certs.

The bot image (ghcr.io/meetbot-dev/bot:latest) is pulled on demand by the worker. Real Chrome + Xvfb + ffmpeg, ~750 MB compressed.

What's different from hosted

Read the honest list at github.com/meetbot-dev/self-host#limitations-vs-hosted. The headline gaps:

  • Calendar V2 (OAuth-managed scheduling) is off — needs public callback URLs that self-hosters can't always offer. Workaround documented in the repo README.
  • Email intake (bot@meetbot.dev) runs on Cloudflare Workers in hosted; self-hosters wire their own SMTP receiver.
  • Stripe billing is off by default — you're not paying us. Wire it only if you bill your own customers downstream.
  • Hosted dashboard (the Next.js UI) isn't shipped — bring your own frontend or call the API directly.

Everything else is identical: same bot adapters, same per-speaker audio, same webhook signatures, same migrations.

Quick start

git clone https://github.com/meetbot-dev/self-host
cd self-host
cp .env.example .env  &&  $EDITOR .env
./init-db.sh
docker compose up -d
curl https://api.your-domain.com/healthz   # → ok

Then dispatch your first bot — it's the same SDK call as hosted, just point baseUrl at your own API endpoint.

import { createMeetbot } from "@meetbot/sdk";

const meetbot = createMeetbot({
  apiKey: process.env.MEETBOT_ADMIN_SECRET!,
  baseUrl: "https://api.your-domain.com",
});

await meetbot.dispatchBot({
  url: "https://meet.google.com/abc-defg-hij",
  externalId: "selfhost-test",
  webhooks: { onFinalize: "https://yours.example/hook" },
});

Working sample: samples/self-host/.

See also

  • Sizing recommendations — vCPU + RAM per concurrent-bot count
  • Storage — any S3-compat (R2, MinIO, Wasabi, Hetzner, …)
  • Updatesdocker compose pull && docker compose up -d
  • Backups — pg_dump cron + object-storage lifecycle

On this page