Getting started

Deploy to Cloudflare

One click provisions the Worker, database, storage, queues and AI bindings on your account.

The Deploy button

Deploy to Cloudflare

Clicking it will:

  1. Fork the repository into your GitHub or GitLab account.
  2. Create every resource declared in wrangler.jsonc on your Cloudflare account:
BindingResourcePurpose
DBD1 databaseUsers, inboxes, emails, labels, webhooks
BUCKETR2 bucketRaw MIME, large bodies, attachments
OAUTH_KVKV namespaceOAuth grants and tokens for MCP clients
JOBSQueue (+ DLQ)Labeling and webhook delivery
INBOX_HUBDurable ObjectRealtime fan-out, wait long-polls
COUNTERSDurable ObjectRate limits, flood protection, budgets
AIWorkers AISmart labels with Clef
  1. Ask for the secrets from .dev.vars.example: BETTER_AUTH_SECRET (generate one with openssl rand -base64 32) and the AWS keys for Amazon SES (see below).
  2. Build the app, apply D1 migrations and deploy. Workers Builds keeps redeploying on every push to your fork.

Amazon SES

All mail is received and sent through Amazon SES in your own AWS account — reliable deliverability, any DNS provider, and about $0.10 per 1,000 emails.

  1. Pick a region that supports SES receiving (e.g. eu-west-1, us-east-1, us-west-2) and set it as AWS_REGION.
  2. Create an IAM user with this policy and put its access key into AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY:
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ses:*",
				"sns:*",
				"s3:CreateBucket",
				"s3:PutBucketPolicy",
				"s3:GetObject",
				"s3:DeleteObject",
				"sts:GetCallerIdentity"
			],
			"Resource": "*"
		}
	]
}
  1. New SES accounts start in the sandbox (sending only to verified addresses). Request production access before sending to real recipients — receiving works right away.

After the deploy

  1. Open the Worker URL and attach a custom domain such as mail.example.com — Amazon SNS only delivers to HTTPS URLs. Set APP_URL to it.
  2. Create the first account — it owns the instance. Everyone with the owner or admin role can change instance settings; a self-hosted instance belongs to one team.
  3. The setup wizard checks bindings, sets up SES receiving with one click (S3 bucket, SNS topic, receipt rule), adds your domain with its DNS records and waits for a test mail.

Set APP_URL to your public URL once you attach a custom domain. It is used for OAuth metadata, links in emails and attachment URLs.

VariableExampleWhy
APP_URLhttps://mail.example.comStable public URL
MAIL_FROMSquadmail <noreply@example.com>Sender for invites and resets
AWS_REGIONeu-west-1Amazon SES region
SIGNUP_MODEinviteopen, invite or closed

See the full configuration reference.

Updating

Pull upstream changes into your fork. Workers Builds rebuilds, applies new migrations (wrangler d1 migrations apply DB --remote is part of the deploy script) and deploys.

Edit this page on GitHub