Skip to documentation

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 ConvexConvex Cloud
Where your data livesYour serverConvex
Database to operate and back upYesNo
Cost and limitsYour serverYour Convex plan
Public hostnames on your serverDashboard, API, callbacksDashboard 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

  1. In the Convex dashboard, create a project.
  2. Open the deployment you want Opensend to use, then Settings → URL & Deploy Key.
  3. 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

bash
curl -fsSL https://opensend.cc/install.sh | sh -s -- install \
  --convex cloud --domain mail.example.com

The 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:

bash
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-backup

Convex 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:

bash
docker compose run --rm migrate logs
docker compose run --rm migrate env list

You can also use the Convex dashboard for your deployment. The optional debug dashboard container applies only to self-hosted Convex.