Install via Docker Compose

Drop the image into Coolify, CapRover, Dokploy, or your own compose stack.

compose.yml

Minimum viable setup — port 3000, one named volume, two env vars:

services:
  maillayer:
    image: ghcr.io/mddanishyusuf/maillayer-pro:1
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - maillayer-data:/app/data
    environment:
      AUTH_SECRET: ${AUTH_SECRET}
      APP_URL: ${APP_URL}

volumes:
  maillayer-data:

Create .env next to your compose file with both values:

# Required: public URL where this install is reachable.
# Used for tracking-link generation, unsubscribe URLs, and the
# domain reported to the license server during activation.
APP_URL=https://maillayer.example.com

# Required (or generated on first boot — see callout below).
# Decrypts every stored provider credential — back this up.
AUTH_SECRET=$(openssl rand -base64 48)

Then start it:

docker compose up -d
APP_URL is not optional in production
If you don't set APP_URL, the install falls back tohttp://localhost:3000 internally — license activation will fail withinvalid_domain and tracking links inside emails will point at localhost. Set it to whatever your reverse proxy serves the install at (e.g.https://maillayer.example.com).
AUTH_SECRET is optional
If you skip setting it, the container generates one at first boot and writes it to/app/data/.auth_secret in the volume. Subsequent restarts pick it up automatically. Just don't lose the volume.

Coolify

New Application → Docker Image → enter ghcr.io/mddanishyusuf/maillayer-pro:1. In the volumes tab map/app/data to a Coolify-managed volume. Set AUTH_SECRET in the environment variables tab.

CapRover / Dokploy

Both accept a docker-compose.yml directly. Paste the snippet above into their compose UI, set the env vars, deploy.

Tag pinning

  • :1 — pinned to major version 1 (recommended). Pulls patches and minors; never breaking changes.
  • :1.0.0 — exact version. Maximum stability, manual updates.
  • :latest — always the most recent release. Risky if breaking changes ship.

Reverse proxy / TLS

The container speaks plain HTTP on port 3000. Front it with Caddy, Traefik, nginx, or Coolify's built-in proxy. Update APP_URL to match the public HTTPS URL once your proxy is live (e.g. https://mail.example.com) and docker compose up -d --force-recreate so the change takes effect — both license activation and tracking links read from this env var.

Maillayer auto-detects when its bundled Caddy sidecar isn't present (xcloud, Coolify, and any compose without it) and hides the in-app Settings → Domain page. To make that explicit and skip the runtime detection, set MAILLAYER_NO_CADDY=1 in your environment:

environment:
  AUTH_SECRET: ${AUTH_SECRET}
  APP_URL: ${APP_URL}
  MAILLAYER_NO_CADDY: "1"