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