Ask AI about this page

Install with Docker

This is the recommended install path — one command, one persistent volume, works the same on any Linux VPS.

View on Docker Hub

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 compose plugin
  • 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
Terminal showing docker compose up -d output
docker compose up -d pulling and starting the SubsiMail container

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.