Setup sequence
1
Choose Compose or Helm
Use Docker Compose for a single-host install. Use Helm for Kubernetes. Both deployment paths run the same service graph and require the same admin setup inputs.
2
Pick the public hostname
The public hostname must route to the web server. The same origin serves the browser app and the Worker ingest endpoint:The hosted AgentTeam Email deployment uses
https://app.agentteam.email as this public app hostname. For a self-hosted instance, replace that with the hostname you operate.3
Expose only the web server
The web server is the only public service. WildDuck, Haraka, ZoneMTA, Rspamd, MongoDB, Redis, and mail-control must remain internal.If your host or cluster is not directly public, route the public hostname through operator-owned ingress such as Cloudflare Tunnel, Tailscale Funnel, or a reverse proxy. See Public Ingress.
4
Create the admin Cloudflare OAuth app
Create one Cloudflare OAuth app for the admin instance. The web app uses this OAuth app when signed-in users connect their own Cloudflare accounts and domains.Configure the required Cloudflare OAuth scopes listed in Environment Variables.Configure the OAuth client for Authorization Code with PKCE and token endpoint authentication method
none. OAuth access and refresh tokens from connected users are stored by Better Auth in the web server database and must not be copied into Compose files, Helm values, browser-visible config, logs, or docs.5
Configure the service-level Cloudflare Worker
Configure the service-level Cloudflare Worker values for the admin instance. The web server provisions this Worker at startup and uses it only for authenticated
POST /oauth2/token forwarding to Cloudflare’s OAuth token endpoint when server egress is challenged.This Worker is not a customer-domain Worker. Use an operator-owned Cloudflare account ID, an API token with account-level Workers Scripts read/write access, a deployment-specific Worker name, the account workers.dev subdomain, and a distinct backend-to-Worker password.See Environment Variables for the Compose variables and Helm for the equivalent chart values.6
Create the admin R2 archive bucket
Create one Cloudflare R2 bucket owned by the admin instance. AgentTeam Email uses this bucket as the durable archive for inbound and outbound mail.The admin instance needs two R2 credential surfaces:
The R2 API token is used only to issue prefix-scoped temporary Worker credentials. It must not be used for user-domain Worker deployment, Email Routing, DNS changes, or outbound Cloudflare Email Sending.
7
Generate internal secrets
Generate a distinct secret for every secret-valued setting in every environment.Use a base64url-encoded 32-byte key for Use long random tokens for service tokens and passwords:The complete Compose variable list is in Environment Variables. Helm uses equivalent values in Helm.
AT_EMAIL_ADMIN_ENCRYPT_SECRET_KEY:8
Configure admin transactional SMTP
Admin SMTP is only for system transactional email from the admin instance, such as account and notification mail. It is not used for mail sent from provisioned user domains.User-domain inbound and outbound mail is configured through the connected Cloudflare domain flow.
9
Start the stack
Start the runtime with Compose or Helm after the required admin inputs are set. Required values fail closed:
the deployment must not start when required hostnames, secrets, OAuth values, or R2 values are missing.
10
Sign in and provision the first domain
Open the public hostname, sign in, connect Cloudflare from the web UI, select the mail zone, and provision
the domain. Domain provisioning creates the DNS, Email Routing, Worker, R2 temporary credential, and Worker
binding state for that user’s domain.
11
Validate the deployment
Run the checks in Validation to verify health, ingest routing, archive writes, mailbox delivery, and outbound sending.
Required admin inputs
What setup does not do
- Do not put user-domain Cloudflare API tokens in environment variables.
- Do not use admin SMTP for user-domain sending.
- Do not expose WildDuck, Haraka, ZoneMTA, Rspamd, MongoDB, Redis, or mail-control publicly.
- Do not configure Worker runtime bindings by hand in Compose or Helm.
- Do not create a global Worker webhook signing secret or separate global Worker ingest URL.