Install with Docker
This is the recommended install path — one command, one persistent volume, works the same on any Linux VPS.
New in 8: the container also serves open, click and unsubscribe links on a tracking-only port (3001 by default, TRACKING_PORT; off disables it). Uncomment the port mapping in docker-compose.yml to publish it. See Tracking domain & VPN.
Requirements
- Docker Engine + the
docker composeplugin - A small VPS (1 vCPU / 2 GB RAM recommended; the app and its built-in database idle at roughly half a gigabyte)
- A domain pointed at the server, if you want automatic HTTPS (optional for local/internal use)
Run it
No repo to clone — the image is published on Docker Hub. Save this as docker-compose.yml in an empty directory on your server:
services:
subsimail:
image: subsimail/subsimail:latest
restart: unless-stopped
ports:
- "3000:3000"
- "443:443"
volumes:
- subsimail-data:/app/data
# Give the built-in database time to shut down cleanly on `docker stop`.
stop_grace_period: 30s
environment:
# Set these to enable automatic TLS via Let's Encrypt (rustls-acme).
# Leave unset to run on plain HTTP (default, e.g. behind your own
# reverse proxy, or for local testing).
# ACME_DOMAIN: mail.yourdomain.com
# ACME_EMAIL: you@yourdomain.com
# ACME_PRODUCTION: "true"
# Behind Nginx, Caddy, Traefik, or a Cloudflare Tunnel? Uncomment this
# so SubsiMail trusts the X-Forwarded-For header instead of logging
# every visitor as the proxy container's own IP.
# TRUSTED_PROXY: "true"
volumes:
subsimail-data:
Then start the stack:
docker compose up -d
This maps ports 3000 (app) and 443 (HTTPS, if enabled) and creates a named volume, subsimail-data, mounted at /app/data for the database and uploads.
Once it's up, open http://your-server:3000 — you'll land on the license activation screen. Continue with first-run setup.
Automatic HTTPS (optional)
SubsiMail can provision its own TLS certificate via Let's Encrypt (rustls-acme) if you set these environment variables in docker-compose.yml before starting:
ACME_DOMAIN: mail.yourdomain.com
ACME_EMAIL: you@yourdomain.com
ACME_PRODUCTION: "true"
Leave these unset to run on plain HTTP — the default, and the right choice if you're putting SubsiMail behind your own reverse proxy (nginx, Caddy, Traefik) that already terminates TLS. In that case, set TRUSTED_PROXY: "true" too (shown commented-out above) so SubsiMail reads the real visitor IP from the proxy's forwarded-for header rather than logging every request as the proxy container's own address — see Reverse proxy & SSL for the per-proxy setup.
Your license is bound to the domain you activate it against (see License & domain binding). Whatever domain you plan to use long-term, set it up before or during first-run setup — changing it later means re-issuing the license from your account.
Where your data lives
Everything — contacts, campaigns, connected-account tokens, users — lives in the bundled PostgreSQL database inside the subsimail-data volume. Don't copy that volume's files while the container is running — use backup-db (see Updating safely) for a consistent backup. Updating the container image (see Updating safely) never touches this volume.