Getting Started

Installation

Cleanmails runs as a Docker Compose stack on any Linux VPS. This page covers the full manual installation process. For the fastest path, see Quick Deploy.

System Requirements

ComponentMinimumRecommended
OSUbuntu 22.04 / Debian 12Ubuntu 22.04 LTS
CPU1 vCPU4 vCPU
RAM1 GB4 GB
Disk5 GB SSD50 GB SSD

Manual Installation

1. Install Docker

bash
curl -fsSL https://get.docker.com | sh
systemctl enable docker
systemctl start docker

2. Create the application directory

bash
mkdir -p /opt/cleanmails
cd /opt/cleanmails

3. Create the environment file

/opt/cleanmails/.env
# Domain
DOMAIN=app.yourdomain.com

# Database
DB_PASSWORD=$(openssl rand -hex 16)
DATABASE_URL=postgres://cleanmails:${DB_PASSWORD}@postgres:5432/cleanmails?sslmode=disable

# Redis
REDIS_URL=redis://redis:6379

# Security (REQUIRED — auto-generated by installer)
ENCRYPTION_KEY=$(openssl rand -hex 32)
JWT_SECRET=$(openssl rand -hex 32)

# App
BASE_URL=https://app.yourdomain.com
API_PORT=8080
GIN_MODE=release
ALLOWED_ORIGINS=https://app.yourdomain.com
Generate unique secrets

Run openssl rand -hex 32 to generate the ENCRYPTION_KEY and JWT_SECRET. Never reuse keys across instances. The ENCRYPTION_KEY encrypts all sender passwords and integration tokens using AES-256-GCM.

4. Create docker-compose.prod.yml

Copy the production docker compose file from your download. It includes six services:

ServicePurpose
postgresPostgreSQL 16 database
redisRedis 7 for task queue (Asynq)
apiGo API server (Gin framework)
workerBackground job processor
frontendNext.js React dashboard
caddyReverse proxy + auto SSL

5. Build Docker images

bash
# Build the API server
docker build -t cleanmails-api:latest -f Dockerfile.api .

# Build the background worker
docker build -t cleanmails-worker:latest -f Dockerfile.worker .

# Build the frontend
docker build -t cleanmails-frontend:latest -f Dockerfile.frontend .

6. Configure firewall

bash
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 25/tcp
echo "y" | ufw enable

7. Start the stack

bash
docker compose -f docker-compose.prod.yml up -d

8. Verify

bash
# Check all containers are running
docker compose -f docker-compose.prod.yml ps

# Check health endpoint
curl http://localhost:8080/health

# Check logs
docker compose -f docker-compose.prod.yml logs -f api

SSL Configuration

The included Caddy container handles SSL automatically. Point your domain's A record to your server IP. The installer generates a Caddyfile that routes:

Caddyfile
yourdomain.com {
    handle /api/* {
        reverse_proxy api:8080
    }
    handle /health {
        reverse_proxy api:8080
    }
    handle /t/* {
        reverse_proxy api:8080
    }
    handle /unsubscribe/* {
        reverse_proxy api:8080
    }
    handle {
        reverse_proxy frontend:3000
    }
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        Strict-Transport-Security "max-age=31536000"
    }
}

Caddy will auto-provision a Let's Encrypt certificate on first request.

Updating

bash
cd /opt/cleanmails
bash scripts/update.sh

The update script downloads the latest release from S3, rebuilds all Docker images, and restarts the stack with zero downtime. You can also trigger updates from the admin panel (Settings → System → Check for Updates).