Self-Hosting Configuration
Complete reference for Docker environment variables, Convex backend variables, service topology, and volume persistence.
This page is the complete configuration reference for a self-hosted Owlat instance. For step-by-step setup, see Self-Hosting.
Docker .env vs Convex env vars Owlat uses two separate configuration layers. Mixing them up is the most common setup mistake.
- Docker
.env — read by Docker Compose at container startup. Controls ports, secrets shared between containers, and browser-facing URLs. - Convex environment variables — read by serverless functions inside the Convex backend. Set after deployment via
npx convex env set. Controls application behavior: email provider, auth secrets, sender identity, integrations.
These go in the .env file at the project root. Docker Compose reads them when starting containers.
| Variable | Required | Default | Description |
|---|
INSTANCE_SECRET | Yes | — | Convex backend instance identity. Generate with openssl rand -hex 32. |
CONVEX_ADMIN_KEY | Yes | — | Admin key for deploying functions. Generated after first boot via docker compose exec convex ./generate_admin_key.sh. |
These must be reachable from the user's browser — do not use Docker-internal hostnames.
| Variable | Required | Default | Description |
|---|
NUXT_PUBLIC_CONVEX_URL | Yes | http://localhost:3210 | Convex backend URL (browser → Convex). |
NUXT_PUBLIC_CONVEX_SITE_URL | Yes | http://localhost:3211 | Convex site proxy URL (browser → HTTP actions). |
NUXT_PUBLIC_SITE_URL | Yes | http://localhost:3000 | Web application URL. |
| Variable | Required | Default | Description |
|---|
MTA_API_KEY | Yes | — | Shared secret for Convex → MTA authentication. Generate with openssl rand -base64 32. |
MTA_WEBHOOK_SECRET | Yes | — | HMAC secret for MTA → Convex webhook callbacks. Generate with openssl rand -base64 32. |
EHLO_HOSTNAME | Yes | mail.localhost | SMTP EHLO/HELO hostname. Must match your server's rDNS PTR record in production. |
RETURN_PATH_DOMAIN | Yes | bounces.localhost | Domain for VERP bounce return-path addresses. Needs an MX record pointing to your server. |
IP_POOLS_TRANSACTIONAL | No | 127.0.0.1 | Comma-separated IPs for transactional email delivery. |
IP_POOLS_CAMPAIGN | No | 127.0.0.1 | Comma-separated IPs for campaign/marketing email delivery. |
DKIM_KEYS | No | {} | DKIM signing keys as JSON. See DNS & Email Setup. |
WORKER_CONCURRENCY | No | 50 | Number of parallel MTA worker threads. |
MTA_LOG_LEVEL | No | info | MTA log verbosity: debug, info, warn, error. |
All ports can be changed if the defaults conflict with existing services.
| Variable | Default | Service |
|---|
CONVEX_PORT | 3210 | Convex backend API |
CONVEX_SITE_PORT | 3211 | Convex HTTP actions |
DASHBOARD_PORT | 6791 | Convex dashboard |
WEB_PORT | 3000 | Web application |
MTA_HTTP_PORT | 3100 | MTA HTTP API |
MTA_SMTP_PORT | 25 | MTA SMTP (bounce processing) |
REDIS_PORT | 6379 | Redis |
CLAMAV_PORT | 3310 | ClamAV |
NEST_PORT | 3001 | Admin panel |
| Variable | Default | Description |
|---|
NUXT_PUBLIC_POSTHOG_API_KEY | — | PostHog project API key for client-side tracking. |
NUXT_PUBLIC_POSTHOG_HOST | https://eu.i.posthog.com | PostHog instance URL. |
These are set after deploying functions. They control application-level behavior inside the Convex backend.
npx convex env set VAR_NAME "value" \
--url http://localhost:3210 \
--admin-key <your-admin-key>
| Variable | Description |
|---|
SITE_URL | Public site URL for auth redirects (e.g., http://localhost:3000). |
CONVEX_SITE_URL | Convex site URL for tracking pixels and unsubscribe links. |
BETTER_AUTH_SECRET | Secret for signing auth sessions. Generate with openssl rand -base64 32. |
UNSUBSCRIBE_SECRET | HMAC secret for signed unsubscribe tokens. Generate with openssl rand -base64 32. |
EMAIL_PROVIDER | Email provider: mta (default), ses, or resend. |
MTA_API_URL | MTA service URL. Use http://mta:3100 for Docker networking. |
MTA_API_KEY | Must match the MTA_API_KEY in Docker .env. |
MTA_WEBHOOK_SECRET | Must match the MTA_WEBHOOK_SECRET in Docker .env. |
| Variable | Default | Description |
|---|
DEFAULT_FROM_EMAIL | noreply@example.com | Default sender email address. |
DEFAULT_FROM_NAME | Owlat | Default sender display name. |
DEFAULT_FROM_DOMAIN | mail.owlat.app | Domain for system emails (invitations, etc.). |
ALLOWED_ORIGINS | — | Comma-separated CORS origins (e.g., http://localhost:3000,http://localhost:3001). |
| Variable | Description |
|---|
GOOGLE_SAFE_BROWSING_API_KEY | Google Safe Browsing API v4 key for URL reputation checking. |
MTA_INTERNAL_URL | MTA URL for ClamAV attachment scanning (e.g., http://mta:3100). |
POSTHOG_API_KEY | PostHog API key for server-side analytics. |
POSTHOG_HOST | PostHog instance URL (default: https://eu.i.posthog.com). |
OPENROUTER_API_KEY | OpenRouter API key for AI-powered translations. |
OPENAI_API_KEY | OpenAI API key for AI translations (fallback). |
For the complete variable reference including AWS SES, Resend, and control plane variables, see Environment Variables.
| Service | Ports | Depends On | Healthcheck |
|---|
| convex | 3210 (API), 3211 (site proxy) | — | curl -f http://localhost:3210/version every 15s |
| convex-dashboard | 6791 | convex (healthy) | — |
| web | 3000 | convex (healthy) | — |
| mta | 3100 (HTTP), 25 (SMTP) | redis (healthy), clamav (healthy), convex (healthy) | — |
| redis | 6379 | — | redis-cli ping every 10s |
| clamav | 3310 | — | clamdcheck every 60s (120s start delay) |
| nest | 3001 | convex (healthy) | — |
| convex-deploy | — | convex (healthy) | One-shot (deploy profile) |
| nest-api-deploy | — | convex (healthy) | One-shot (deploy profile) |
| Volume | Persists | Backup Priority |
|---|
convex-data | Database, file storage, vector indexes | Critical — all application data |
redis-data | MTA job queue (AOF) | Medium — in-flight email jobs |
clamav-data | Virus definition signatures | Low — re-downloads automatically |