Skip to content

Self-hosting

Deploy XID as three isolated Workers on your Cloudflare account, with the complete data, queue, consistency, email, routing, and production-control inventory.

Required bindings

Binding Purpose
xid-site, xid-console, xid Deploy three Workers: Nimbus Site owns the apex documentation and www redirect, Console owns /console, and Core owns Hosted Auth, protocols, APIs, jobs, and identity state. Site and Console bind only ASSETS.
DB, CACHE, STORAGE Core uses D1 for tenant-scoped relational data, KV only for read-heavy caches, and R2 for private objects. Strongly consistent state never belongs in KV.
EMAIL, ANALYTICS, SITE_WORKER, CONSOLE_WORKER, ASSETS Core binds Email Service and Analytics Engine, plus one-way Service Bindings to Site and Console for exact-route query fallback. Frontend Workers never bind back to Core.
SESSION_REVOCATION, WEBAUTHN_CHALLENGE, OAUTH_STATE, PAR_STORE, DEVICE_FLOW, RATE_LIMITER, AUDIT_SEQ, METERING, GUEST_STORE, CIBA_STATE, IMPERSONATION_GRANTS Eleven SQLite-backed Durable Objects serialize sessions, challenges, OAuth, PAR, device and CIBA state, rate limits, audit order, metering, guests, and impersonation grants.
xid-email, xid-whatsapp, xid-sms, xid-audit, xid-webhook, xid-metering, xid-scim-sync, xid-privacy Eight source Queues move email, WhatsApp, SMS, audit, webhook, metering, outbound SCIM, and privacy work off authentication paths.
8 source DLQs + 8 persistence-failure Queues Each source Queue requires its own dead-letter Queue and persistence-failure quarantine, for 24 Queues total. The shared xid-dlq is obsolete and must not be used.

Production configuration

Secret Purpose
KEK, PEPPER, BOOTSTRAP_TOKEN Production and staging require KEK, PEPPER, and BOOTSTRAP_TOKEN as Workers Secrets. Never place them in variables, D1, source files, or build logs.
EMAIL_FROM_ADDRESS, EMAIL_FROM_NAME Set the non-secret sender identity explicitly. XID validates the address and fails closed. Arbitrary-recipient Email Sending requires Workers Paid; D1, SQLite-backed Durable Objects, and Queues are available on Workers Free within their limits.
TURNSTILE_SITE_KEY + TURNSTILE_SECRET; CLOUDFLARE_FOR_SAAS_* Configure Turnstile as a complete site-key and secret pair. Optional Cloudflare for SaaS hostnames require a zone, API token, active fallback origin, DNS, and routes. Zone WAF and edge rate limiting remain separate controls; application limits fail closed in RATE_LIMITER.

Deployment checks

Before declaring production ready, reconcile all 24 Queues, apply D1 migrations, build all three Workers, and verify apex, www, wildcard DNS, health, discovery, JWKS, and Hosted Auth. Then record live evidence for Email, DLQ replay, privacy export and 30-day erasure, hourly and daily Cron, Analytics, Turnstile, and custom hostnames. Local L0-L3 evidence is not L4; every unrun live check is UNKNOWN. The full operator runbook is maintained at https://github.com/StringKe/xid/blob/main/docs/deployment.md.

pnpm install
pnpm run cloudflare:queues:plan
pnpm run cloudflare:queues:create
pnpm run cloudflare:queues:check
pnpm check
pnpm test
pnpm build
pnpm smoke:l2-l3
pnpm smoke:three-workers

# Merge a reviewed, signed commit to main so Cloudflare Workers Builds deploys all three Workers.
curl https://<your-domain>/v1/health
curl https://<your-domain>/.well-known/openid-configuration
curl https://<your-domain>/jwks
curl https://<your-domain>/auth/config
curl -I https://www.<your-domain>/
Navigation

Type to search...

Use arrow keys to navigateEnter to selectEscape to close