Guides / Self-hosting

Self-hosting

Run thump on your own Cloudflare account — resource provisioning, secrets, first deploy, CI/CD, and upgrades. Free plan except real-browser checks.

On this page

Self-hosting thump

thump runs entirely on Cloudflare: Workers (API + dashboard + status pages), D1 (config + state), KV (sessions + cache), Durable Objects (probe schedulers + incident coordinator), and Analytics Engine (probe time-series). Everything fits the free Workers plan except the browser monitor kind (real-browser checks), which needs Browser Rendering on a paid plan — every other feature degrades cleanly without it.

This guide takes you from clone to a working deployment on your own Cloudflare account.

1. Prerequisites

you want custom domains for the app itself or for status pages

git clone https://github.com/rbaljinder/thump && cd thump
pnpm install
cd apps/api
pnpm exec wrangler login

2. Create the Cloudflare resources

pnpm exec wrangler d1 create thump-db
pnpm exec wrangler kv namespace create SESSIONS

Each command prints an id. Open apps/api/wrangler.toml and replace:

default *.workers.dev URL to start)

The Analytics Engine dataset needs no provisioning — it is created on the first write. Durable Objects are declared in the file and created on deploy.

3. Apply the database migrations

pnpm exec wrangler d1 migrations apply thump-db --remote

Idempotent — safe to re-run on every upgrade (the deploy workflow does exactly this before each code deploy).

4. Configure auth (GitHub OAuth)

Create a GitHub OAuth app (github.com → Settings → Developer settings → OAuth Apps):

Then set the public half in wrangler.toml [vars] (GITHUB_CLIENT_ID, GITHUB_REDIRECT_URI) and the secret half:

pnpm exec wrangler secret put GITHUB_CLIENT_SECRET

Google OAuth works the same way (GOOGLE_* vars + wrangler secret put GOOGLE_CLIENT_SECRET) and is optional — GitHub-only sign-in is fine. Passkeys need no configuration.

5. Secrets

Set with pnpm exec wrangler secret put <NAME> from apps/api/. Local equivalents go in apps/api/.dev.vars (gitignored).

Core (set these):

SecretPowersNotes
GITHUB_CLIENT_SECRETSign-inFrom step 4
THUMP_VAULT_KEYSecrets vault encryption at restopenssl rand -hex 32. Without it, production vault writes fail closed
CF_API_TOKENUptime charts, latency history, world mapAPI token with Account Analytics: Read
RESEND_API_KEYEmail alerts, invitations, status-page subscriber emailresend.com; verify your sending domain, set RESEND_FROM_EMAIL in [vars]

Optional, feature-gated (skip freely — each degrades with a clear message):

Secret / varPowers
GOOGLE_CLIENT_SECRET (+ GOOGLE_* vars)Google sign-in
SLACK_CLIENT_SECRET (+ SLACK_* vars)"Add to Slack" OAuth install (pasting a webhook URL works without it)
ANTHROPIC_API_KEYAI drafting + self-repair for browser synthetics
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBERSMS + voice-call alert channels
VAPID_PRIVATE_KEY (+ VAPID_PUBLIC_KEY, VAPID_SUBJECT)Web push notifications — generate with node scripts/generate-vapid-keys.mjs
CF_HOSTNAMES_API_TOKEN (+ CF_ZONE_ID var)Custom domains for status pages (Cloudflare for SaaS; token needs Zone: SSL and Certificates: Edit)
CF_CACHE_PURGE_TOKENEdge-cache purge on incident transitions (Zone: Cache Purge)
OPS_ALERT_WEBHOOK_URLSelf-alerting — a JSON POST when thump's own Worker throws an unhandled error. Needs nothing else configured, so it's the one that works on a fresh deploy
OPS_ALERT_EMAILSame alert by email (requires RESEND_API_KEY)

Watching your own instance

Two layers, both worth turning on:

1. Self-alerting. Set OPS_ALERT_WEBHOOK_URL (and/or OPS_ALERT_EMAIL). When a request throws, thump posts you the error signature, first/last seen, and an occurrence count. Alerts are deduped by signature with a 15-minute cooldown, so a page failing on every request pages you once per window rather than once per request — and the count tells you how bad it is. With neither set, errors are logged only (the previous behaviour).

2. Self-monitoring. POST /api/v1/admin/bootstrap-self-monitoring (platform-admin only, idempotent) creates thump's own monitors and publishes them at /status/thump. It covers the public surfaces and two authed API checks — the dashboard overview and check history — because unauthed checks alone will happily stay green while a signed-in page is 500ing.

The authed checks need a token: create a personal access token under Settings → API tokens, then store it in the vault under Secrets with the exact name THUMP_SELF_PAT. The bootstrap response tells you if it's missing. Until then those two checks fail with an auth error.

6. First deploy

The Worker serves the built dashboard itself, so build the web app first:

cd ../web && pnpm run build && cd ../api
pnpm exec wrangler deploy

Visit your domain: the landing page should render, and sign-in should round-trip through GitHub. The 1-minute cron trigger (declared in wrangler.toml) starts the incident coordinator automatically.

Browser Rendering (optional, paid plans): the [browser] binding is deliberately absent from the committed wrangler.toml (wrangler v3 rejects it in local dev). To enable browser monitors, append it just before deploying — this is exactly what the CI workflow does:

printf '\n[browser]\nbinding = "BROWSER"\n' >> wrangler.toml
pnpm exec wrangler deploy
git checkout wrangler.toml

7. Continuous deploys (GitHub Actions)

.github/workflows/deploy.yml deploys on every push to main: builds the web app, applies D1 migrations, appends the browser binding, and runs wrangler deploy. To use it on your fork, set two repo secrets:

permissions if using custom domains)

8. Post-deploy checklist

monitors for your own deployment.

schedule — see the monitoring guide and on-call guide.

Upgrading

git pull
pnpm install

…then push to main (CI path) or repeat step 6 (manual path). Migrations are ordered, additive, and idempotent; code and schema deploy together.

Local development

No Cloudflare account needed — everything runs in wrangler's local simulator:

cd apps/web && pnpm run build && cd ../api
pnpm exec wrangler d1 migrations apply DB --local
pnpm exec wrangler dev --port 4001 --local --var DEV_AUTO_LOGIN:true

DEV_AUTO_LOGIN=true signs you in as a local "Dev Admin" without OAuth. See CONTRIBUTING.md for the test suites and project conventions.