BOX OXDocs

Get started

Deploy Box Ox

Deploy the app, then protect owner access and connect your mail domain.

On this page

Before you start#

Review the Workers Free and Paid requirements before deploying. Box Ox uses one download. Box Ox is free. The installer picks the inbox install on Cloudflare Workers Free or the full install on Workers Paid. Read the Workers Free guide for included features and testing status.

Use Node.js 22 or later on a current security release (22.23.4, 24.22.1 or 26.12.1 and newer as of October 21, 2026; odd-numbered lines such as 25 are unsupported), pnpm 10.25.0, Git, a Bash shell, and a Cloudflare account with R2 enabled. Workers Paid is needed for the full profile. The root deployment helper is a Bash script. On Windows, use a configured Bash environment such as WSL. The web app can run at boxox.<your-account-subdomain>.workers.dev; a custom website domain is optional. The installer can register a free account subdomain through Cloudflare's API when none exists. Sending and receiving mail still require a domain you control. The account must own the DNS zones you onboard. Use Cloudflare Access for owner and member sign-in. Require two-factor sign-in on Cloudflare and GitHub. Prefer security keys.

Email Service sending is for transactional messages from domains you own or have permission to use. Review the service terms. Get confirmation from Cloudflare before relying on it for general-purpose conversational sending. Box Ox has no broadcasts, audiences, or marketing campaigns.

Receiving moves the domain's mail to Box Ox. Enabling Email Routing can replace existing MX records. Choose sending only if you intend to keep receiving mail at Google Workspace, Microsoft 365, or another provider.

The wizard shows existing MX records and requires confirmation before replacing a foreign mail provider. Back up the existing DNS configuration before making that choice. Subdomains can send. Catch-all receiving requires a zone apex.

Review and deploy the source#

Download the published source snapshot from boxox.dev. Verify its SHA-256 against the published checksum, unzip it, and review the source. The checksum detects a changed download; it is not a signed release or independent trust proof. The snapshot includes no Git history. Initialize a local repository so deployment can identify your source:

sh
cd boxox-v2
git init
git add .
git commit -m "Import reviewed Box Ox source"
pnpm install --frozen-lockfile
pnpm exec wrangler login
pnpm exec wrangler whoami

Using a reviewed fork or signed tag

If you already have access to the upstream repository, use your reviewed fork instead. Use reviewed signed release tags when available, rather than updating directly from main. Verify the tag signature against a trusted maintainer identity, then review the changes before deploying. For example, replace REVIEWED_TAG with the tag you reviewed:

sh
git fetch origin --tags
git tag -v REVIEWED_TAG
git switch --detach REVIEWED_TAG
pnpm install --frozen-lockfile
pnpm exec wrangler login
pnpm exec wrangler whoami

These commands do not establish that a signed release exists. A valid signature from an unknown identity is not sufficient verification.

Automatic plan detection needs Billing Read. A separate BOXOX_BILLING_TOKEN can supply a read-only token from your secret manager. Wrangler OAuth cannot read billing. If needed, check Workers & Pages and set BOXOX_PLAN=free or BOXOX_PLAN=paid. The installer stops before provisioning if it cannot verify the plan and you have not selected one.

Set the installation account and owner identity in the deployment shell:

sh
export CF_ACCOUNT_ID='your-cloudflare-account-id'
export OWNER_EMAIL='you@example.com'
# Optional: omit BOXOX_URL to use your free workers.dev app address.
# export BOXOX_URL='https://mail.example.com'
pnpm run deploy

Use an HTTPS origin for BOXOX_URL, with no path. It configures a Worker custom domain and disables the workers.dev and preview URLs. Without it, the helper discovers your registered account subdomain, enables workers.dev, and sets PUBLIC_URL to https://boxox.<your-account-subdomain>.workers.dev. Configure Access for that hostname. Preview URLs stay disabled in both cases. The Worker rejects owner API requests until Access is configured. If the account has no workers.dev subdomain, the helper registers boxox-<first 12 account-ID characters> and verifies it. Set BOXOX_WORKERS_SUBDOMAIN to choose another name before the first deployment. Existing account subdomains stay unchanged. Set CF_ACCOUNT_ID and OWNER_EMAIL on every deployment. The owner email must match the identity Cloudflare Access verifies.

Use pnpm run deploy, including run. pnpm deploy is a different pnpm command. The script requires a clean Git checkout so its public health response identifies the deployed commit. It builds the SDK and web app, checks workspace types, provisions resources, applies remote D1 migrations, and deploys Worker boxox. For both address options, the script checks that /health reports the deployed source commit. Keep the same BOXOX_URL on subsequent deployments if you use a custom domain.

The helper checks R2 activation before creating resources. On a fresh account, complete Cloudflare's R2 checkout first. It requires a payment method and acceptance of terms even on Workers Free. R2 includes free allowances; Cloudflare bills overages. The installer does not activate subscriptions.

Resources and deployment credentials

The helper finds or creates these account resources:

ResourceDefault name
D1 databaseboxox
KV namespaceboxox-KV
R2 bucketboxox-mail
Vectorize indexboxox-search, 1,536 dimensions, cosine distance
Event queuescf-email-events, cf-email-events-dlq
Webhook queueswebhook-delivery, webhook-delivery-dlq

Wrangler also deploys the Workflows, Durable Object, and declared bindings. The helper writes account resource IDs to ignored .wrangler/deploy/wrangler.json. It creates two secrets on the first deployment and removes the temporary secret file after deployment: AGENT_JWT_SECRET, which signs agent credentials and nothing else, and BOXOX_SIGNING_SECRET, which derives every other key (signed links and images in mail, tracking tokens, raw-download URLs, the domain-connection cookie, Cloudflare OAuth token sealing, webhook secret sealing). Existing secrets remain in place; a later deployment adds only whichever one is missing. Do not rotate either as a routine update: rotating AGENT_JWT_SECRET signs every agent out, and rotating BOXOX_SIGNING_SECRET breaks links in already-sent mail and makes sealed OAuth tokens and webhook secrets unreadable.

The helper reuses resource names in the same account. Review existing resources before installing. The defaults assume one Box Ox installation per account. Wrangler OAuth is the default deployment credential. CI can supply CLOUDFLARE_API_TOKEN with permission to manage the resources in wrangler.jsonc. This deployment credential is separate from the temporary setup token below.