smtp.xem.email; it does not install Dokploy. Review and adapt paths/hostname/UID for other hosts before running it.
Prerequisites
- DNS-only
smtp.xem.emailpoints at the host’s Elastic IP. - EC2 security groups allow public TCP 587 plus HTTP 80 for the existing Traefik HTTP-01 resolver. Never expose container port 2525 publicly in addition to 587.
- Traefik’s dynamic file provider watches
/etc/dokploy/traefik/dynamic, and theletsencryptresolver stores ACME state in that directory’sacme.json. - The backend image runs as UID/GID 65532. The host has Python 3, OpenSSL, CA roots, systemd and util-linux.
host/xem-smtp-certificate.yml requests a public certificate for SMTP via the existing Traefik ACME resolver. It routes HTTPS to noop@internal; an HTTPS 418 is expected and says nothing about SMTP health. It does not terminate STARTTLS. Cloudflare Origin CA is unsuitable for normal SMTP clients.
Install/reconcile the host exporter
Copy this repository to the host, review the scripts, then run as root:/etc/xem are 0750. An atomic current symlink selects the valid pair. A bad renewal leaves the previous certificate untouched and fails the service. Keep ACME storage private; never mount the full ACME JSON into the app. Monitor exporter failures and certificate expiration externally, as this script does not deliver alerts.
The timer runs every five minutes. The backend reloads the certificate from disk at each TLS handshake, so renewal does not require a backend restart. Concurrent handshakes crossing a rotation can retry; do not copy certificate/key files independently into the container. Old version directories are retained for recovery; clean obsolete ones deliberately after validating a renewal.
Dokploy v0.29.13 cannot persist a read-only flag for this bind mount. The installer creates /etc/xem/smtp-readonly as a kernel read-only bind mirror of /etc/xem/smtp; this keeps the source immutable inside redeployed containers even if Dokploy omits the Docker ReadOnly field. Check the effective mount after every host or Dokploy upgrade.
Persistent Dokploy settings
In the backend application (production IDExMUJXUJHPyGKOB_cxn5m):
Save the mount and published port in Dokploy’s application settings, then redeploy. A one-off
docker service update alone is not durable because Dokploy recreates the service spec. Do not publish SMTP through an HTTP router. Stop-first prevents the old task from occupying host port 587 while the new task starts, and introduces a brief interruption.
