Phase 1: Deploy Stalwart in Dokploy

Create a new Docker Compose application in Dokploy.

Use this initial Compose file:

services:
  stalwart-mail:
    image: stalwartlabs/stalwart:v0.16
    restart: unless-stopped

    environment:
      STALWART_PUBLIC_URL: https://mail.example.com

    ports:
      # SMTP reception from other mail servers
      - "25:25"

      # Secure authenticated SMTP submission
      - "465:465"

      # SMTP submission with STARTTLS
      - "587:587"

      # Secure IMAP
      - "993:993"

    expose:
      # Internal HTTP service for Dokploy/Traefik
      - "8080"

    volumes:
      - stalwart_config:/etc/stalwart
      - stalwart_data:/var/lib/stalwart

volumes:
  stalwart_config:
  stalwart_data:

Why explicit port mappings matter

Do not use this form for public mail ports:

ports:
  - "25"
  - "465"
  - "993"

That tells Docker to expose the container port but allows Docker to assign an arbitrary host port.

Mail protocols require fixed public ports:

- "25:25"
- "465:465"
- "587:587"
- "993:993"

Other mail servers always contact port 25. Mail clients expect standard IMAP and submission ports.

Why port 443 is not published

Do not add:

- "443:443"

Dokploy’s Traefik already owns VPS ports 80 and 443 for all web applications.

Stalwart’s web interface will be routed internally through port 8080.

Do not set the Docker hostname

Do not add:

hostname: mail.example.com

The public mail hostname should be configured inside Stalwart, not as the Docker container hostname.

Setting the Docker hostname can make Docker’s internal DNS resolve mail.example.com to a private container address. Dokploy may then incorrectly believe the domain points somewhere other than the public VPS.

Use this separation:

Docker container hostname:
Automatically generated

Stalwart server hostname:
mail.example.com

Public DNS hostname:
mail.example.com

Comments