Self-hosting
Convex Cloud
Run the Opensend dashboard on your server with Convex Cloud as the backend.
When to choose it
By default, Opensend runs its own Convex backend in a container on your server. With Convex Cloud, Convex runs the backend for you, and your server runs only the dashboard, plus the SMTP gateway if you use it. The images are the same in both modes.
| Self-hosted Convex | Convex Cloud | |
|---|---|---|
| Where your data lives | Your server | Convex |
| Database to operate and back up | Yes | No |
| Cost and limits | Your server | Your Convex plan |
| Public hostnames on your server | Dashboard, API, callbacks | Dashboard only |
Choose Convex Cloud when you'd rather not operate a database. Your email content, contacts and logs are then stored by Convex, and your Convex plan's limits and pricing apply.
Create a deployment and a deploy key
- In the Convex dashboard, create a project.
- Open the deployment you want Opensend to use, then Settings → URL & Deploy Key.
- Generate a deploy key. Use a production deployment for real traffic.
The deploy key can change every function and setting in that deployment. Keep it private.
Install
curl -fsSL https://opensend.cc/install.sh | sh -s -- install \
--convex cloud --domain mail.example.comThe installer asks for the deploy key without echoing it. For an unattended install, set CONVEX_DEPLOY_KEY and add --yes.
The deployment URL defaults to https://<deployment-name>.convex.cloud, taken from the key. Use --convex-url for deployments in other regions, which use a different hostname. The HTTP actions URL replaces .convex.cloud with .convex.site. Override it with --convex-site-url if yours differs. Both URLs are shown under Settings → URL & Deploy Key.
The installer writes .env with mode 0600, including OPENSEND_CONVEX=cloud, the deploy key and both URLs. Upgrade and uninstall read the mode from .env. On every start, the one-shot migrate service sets the deployment's environment and deploys the functions with the deploy key, then exits.
DNS and HTTPS
Only the dashboard hostname points at your server. API clients and AWS SES callbacks use the deployment's .convex.cloud and .convex.site URLs directly. Your API base URL is the .convex.site URL.
With Caddy (the default), your server serves:
- the dashboard, over HTTPS;
- custom tracking domains. In cloud mode, a domain's tracking CNAME points at the dashboard hostname, and Caddy forwards
/t/*requests to your deployment with the visitor's IP.
If you use your own proxy instead (--caddy no), route custom tracking hosts the same way. The files to copy from are compose.cloud-caddy.yaml and Caddyfile.cloud in each release.
Server size
Your server runs only the dashboard container, plus the short-lived migrate container on install and upgrade. In our end-to-end runs, the dashboard peaked at about 200 MB of memory and 0.8 cores. migrate peaked at about 700 MB and 1.4 cores while deploying. A server with 1 vCPU and 2 GB of memory covers both. See requirements for how we measured.
Back up
There is no local database volume. Back up with Convex's export, including file storage:
docker compose run --name opensend-backup migrate export --include-file-storage --path /tmp/backup.zip
docker cp opensend-backup:/tmp/backup.zip ./backup.zip
docker rm opensend-backupConvex also keeps its own backups, depending on your plan. Keep .env private and backed up.
Operate it
The migrate service works the same in both modes:
docker compose run --rm migrate logs
docker compose run --rm migrate env listYou can also use the Convex dashboard for your deployment. The optional debug dashboard container applies only to self-hosted Convex.