Deployment guide.
From the Deploy to Cloudflare button on the README to a deployed Worker absorbing inbound messages on every channel. Cloudflare Builds handles the build and deploy from your fork; you’ll set bindings and secrets in the dashboard, register Meta and Discord apps, and wire webhooks. Plan on twenty minutes if your accounts are ready.
Prerequisites
Workers, D1, KV, Queues, and Email Routing enabled. Free tier is fine to start; D1 + AI usage will be the first thing to outgrow it.
A Facebook App with WhatsApp Business and Instagram Graph products. See Facebook app setup.
For Google OAuth sign‑in. Just an OAuth 2.0 client ID: no service account needed.
For the relay bot and slash commands. Discord integration covers the bot setup.
Only if you want to sell paid credit packs. The hosted service uses this; self‑hosters often skip it.
Cloudflare Builds installs rustup, cargo, and Node automatically — no Nix required for CI. For local dev, the flake provides a pinned shell: nix develop.
Step-by-step
-
Fork & connect Cloudflare Builds
The fastest path is the Deploy to Cloudflare button on the repo README. It forks
ananthb/conciergeinto your account, creates a Worker, auto-provisions the bindings declared inwrangler.toml(D1, KV, AI, Email send-binding, Durable Objects, Queues), and connects the fork to Cloudflare Builds so future pushes deploy automatically.To wire it up by hand: fork the repo, then in the dashboard create a Worker named
conciergeand connect the fork under Workers › concierge › Settings › Builds:- Build command: leave default (CF Builds detects
package.jsonand runsnpm install). - Deploy command:
npm run deploy— runscargo install -q worker-build && wrangler deploy.
Local dev still works the usual way:
nix develop(or installcargo,wrangler, the WASM target by hand), thencargo test/wrangler dev. - Build command: leave default (CF Builds detects
-
Bind resources in the dashboard
Under Workers › concierge › Settings › Bindings. The Deploy button auto-provisions matching resources for most of these; you only need to attend to anything missing. Names must match the
bindingvalues inwrangler.toml.Binding What it backs DB→ D1conciergeSQLite for messages, rules, billing, audit log. KVAccount configs, sessions, persona drafts, billing state. AIWorkers AI (LLaMA reply generation + safety classifier). EMAIL(send_email)Outbound forwarding via Email Routing. REPLY_BUFFER→ReplyBufferDODurable Object: buffers inbound messages so we can reply to a batch. APPROVALS_DO→ApprovalsDODurable Object: per-tenant SSE fan-out for the approvals page. SAFETY_QUEUE→concierge-safety+ DLQconcierge-safety-dlqPersona safety classifier pipeline. If absent, persona safety checks stay Pending and AI replies are blocked tenant-wide; static replies still work. -
D1 migrations run on every deploy
The Worker carries its schema in
migrations/*.sql. Thenpm run deployscript runswrangler d1 migrations apply concierge --remoteas part of the deploy; it’s idempotent, safe to re-run, and you don’t need to do anything for it manually.If you ever want to run it yourself (e.g. to apply pending migrations without redeploying),
nix develop --command wrangler d1 migrations apply concierge --remoteworks from a local checkout. -
Set secrets in the dashboard
All runtime secrets live under Workers › concierge › Settings › Variables and Secrets › Secrets. The full reference is on the configuration page; the minimum to deploy is below.
Secret Notes ENCRYPTION_KEY32-byte hex (token encryption). Generate with openssl rand -hex 32.GOOGLE_OAUTH_CLIENT_ID/GOOGLE_OAUTH_CLIENT_SECRETSign-in. META_APP_ID/META_APP_SECRETShared across Facebook Login, Instagram, and WhatsApp. WHATSAPP_ACCESS_TOKEN/WHATSAPP_VERIFY_TOKENPlatform WABA token + webhook verifier. INSTAGRAM_VERIFY_TOKENInstagram DM webhook verifier. DISCORD_PUBLIC_KEY/DISCORD_APPLICATION_ID/DISCORD_BOT_TOKENDiscord interactions + bot. RAZORPAY_KEY_ID/RAZORPAY_KEY_SECRET/RAZORPAY_WEBHOOK_SECRETOnly if billing is enabled. -
Set runtime variables in the dashboard
Plain-text vars live alongside the secrets, under Variables and Secrets › Variables. Set each one per-deployment:
Variable What it’s for CF_ACCESS_TEAMYour Cloudflare Access team name (the subdomain in myteam.cloudflareaccess.com).CF_ACCESS_AUDApplication Audience (AUD) tag from your Access app for /manage/*.WHATSAPP_WABA_IDYour WhatsApp Business Account ID. WHATSAPP_SIGNUP_CONFIG_IDMeta Embedded Signup configuration ID. EMAIL_DOMAINEmail domain you control. Set MX records on its apex and add it to Cloudflare Email Routing. AI_MODEL/AI_FAST_MODELOptional overrides for the reply and injection-scanning models. -
Deploy
Push to
main. Cloudflare Builds runsnpm run deploy— installsworker-build, compiles the Rust crate to WASM, applies any pending D1 migrations, runswrangler deploy. Watch the build log under Settings › Builds; it prints the deployed Worker URL when it’s done.bash terminalgit push origin mainFor an out-of-band deploy from a local checkout,
nix develop --command wrangler deploystill works. -
Configure Meta webhooks
In the Meta Developer Console, point both products at your Worker. Subscribe to the
messagesfield on each.Webhook URLshttps://your-domain/webhook/whatsapphttps://your-domain/webhook/instagram
The verify tokens you set in step 4 are echoed back during webhook setup. See Facebook app setup for screenshots.
-
Set up the Discord bot
- Create a Discord application at discord.com/developers.
- Set the Interactions Endpoint URL to
https://your-domain/discord/interactions. - Create a bot user and copy the token into
DISCORD_BOT_TOKEN. - Register the slash commands
/status,/domains,/rulesvia the Discord API. - Invite the bot to your server with the appropriate permissions.
Detailed walkthrough on the Discord integration page.
-
Set up email routing
Cloudflare Email Routing handles inbound mail for the domain in
EMAIL_DOMAIN. To finish:- In the Cloudflare dashboard, open Email Routing for your email domain.
- Add a catch‑all routing rule: Action → Send to a Worker → select
concierge.
See Email routing for the per-tenant address model.
-
Set up Cloudflare Access for management
- In the Cloudflare dashboard, go to Zero Trust → Access → Applications.
- Create an application for
your-domain/manage/*. - Copy the Application Audience (AUD) Tag and set it as the
CF_ACCESS_AUDvariable under Workers › concierge › Settings › Variables and Secrets. - Add a policy allowing the emails that should have management access.
See the Management panel page.
-
Set up Razorpay optional
- Create a Razorpay account and grab your API keys.
- Set up a webhook at
https://your-domain/webhook/razorpaysubscribing topayment.captured,payment.failed,subscription.activated,subscription.charged,subscription.halted,subscription.cancelled. - Set the webhook secret and API keys as Worker secrets.
See Billing for the credit‑pack model.
Sign in at https://your-domain/ to walk through the in‑app onboarding wizard, then send a test message to your WhatsApp number to confirm the round‑trip.