Skip to content

Instantly share code, notes, and snippets.

@puRe1337
Last active June 10, 2024 01:00
Show Gist options
  • Save puRe1337/cdecc97307cc19c6d899a204b510834e to your computer and use it in GitHub Desktop.
Save puRe1337/cdecc97307cc19c6d899a204b510834e to your computer and use it in GitHub Desktop.
Stalwart Traefik configuration

Test commands with openssl

SMTP 25

openssl s_client -quiet -crlf -starttls smtp -connect mail.example.com:25

SMTP 587

openssl s_client -starttls smtp -quiet -crlf -connect mail.example.com:587

SMTP 465

openssl s_client -quiet -crlf -connect mail.example.com:465

IMAP 143

openssl s_client -crlf -connect mail.example.com:143 -starttls imap -servername mail.example.com

IMAP 993

openssl s_client -quiet -crlf -connect mail.example.com:993

SIEVE 4190

openssl s_client -showcerts -servername mail.example.com -connect mail.example.com:4190

JMAP 443

curl -u admin:'password' https://mail.example.com/.well-known/jmap

authentication.fallback-admin.secret = "SECRET"
authentication.fallback-admin.user = "admin"
certificate.traefik.cert = "%{file:/opt/certs/mail.example.com/cert.pem}%"
certificate.traefik.default = true
certificate.traefik.private-key = "%{file:/opt/certs/mail.example.com/key.pem}%"
cluster.node-id = 1
directory.internal.store = "rocksdb"
directory.internal.type = "internal"
lookup.default.hostname = "mail.example.com"
server.http.permissive-cors = false
server.http.url = "protocol + '://' + key_get('default', 'hostname') + ':' + local_port"
server.http.use-x-forwarded = false
server.listener.http.bind = "[::]:8080"
server.listener.http.protocol = "http"
server.listener.https.bind = "[::]:443"
server.listener.https.protocol = "http"
server.listener.https.tls.implicit = true
server.listener.imap.bind = "[::]:143"
server.listener.imap.protocol = "imap"
server.listener.imap.proxy.override = false
server.listener.imap.socket.override = false
server.listener.imap.tls.implicit = false
server.listener.imap.tls.override = false
server.listener.imaptls.bind = "[::]:993"
server.listener.imaptls.protocol = "imap"
server.listener.imaptls.proxy.override = true
server.listener.imaptls.proxy.trusted-networks.0000 = "172.18.0.0/16"
server.listener.imaptls.socket.override = false
server.listener.imaptls.tls.implicit = true
server.listener.imaptls.tls.override = false
server.listener.sieve.bind = "[::]:4190"
server.listener.sieve.protocol = "managesieve"
server.listener.sieve.proxy.override = true
server.listener.sieve.proxy.trusted-networks.0000 = "172.18.0.0/16"
server.listener.sieve.socket.override = false
server.listener.sieve.tls.implicit = true
server.listener.sieve.tls.override = false
server.listener.smtp.bind = "[::]:25"
server.listener.smtp.protocol = "smtp"
server.listener.smtp.proxy.override = false
server.listener.smtp.socket.override = false
server.listener.smtp.tls.implicit = false
server.listener.smtp.tls.override = false
server.listener.submission.bind = "[::]:587"
server.listener.submission.protocol = "smtp"
server.listener.submission.proxy.override = false
server.listener.submission.socket.override = false
server.listener.submission.tls.implicit = false
server.listener.submission.tls.override = false
server.listener.submissions.bind = "[::]:465"
server.listener.submissions.protocol = "smtp"
server.listener.submissions.proxy.override = true
server.listener.submissions.proxy.trusted-networks.0000 = "172.18.0.0/16"
server.listener.submissions.socket.override = false
server.listener.submissions.tls.implicit = true
server.listener.submissions.tls.override = false
server.max-connections = 8192
server.socket.backlog = 1024
server.socket.nodelay = true
server.socket.reuse-addr = true
server.socket.reuse-port = true
server.tls.certificate = "traefik"
server.tls.enable = true
storage.blob = "rocksdb"
storage.data = "rocksdb"
storage.directory = "internal"
storage.fts = "rocksdb"
storage.lookup = "rocksdb"
store.rocksdb.compression = "lz4"
store.rocksdb.path = "/opt/stalwart-mail/data"
store.rocksdb.type = "rocksdb"
tracer.log.ansi = false
tracer.log.enable = true
tracer.log.level = "info"
tracer.log.path = "/opt/stalwart-mail/logs"
tracer.log.prefix = "stalwart.log"
tracer.log.rotate = "daily"
tracer.log.type = "log"
services:
mail-server:
volumes:
- ./data:/opt/stalwart-mail
- /home/docker/traefik/letsencrypt/dumped:/opt/certs:ro
container_name: stalwart-mail
image: stalwartlabs/mail-server:latest
security_opt: [no-new-privileges:true]
ports:
- 25:25
- 143:143
- 587:587
labels:
- "traefik.enable=true"
# admin ui
- traefik.http.routers.stalwart.rule=Host(`mail.example.com`)
- traefik.http.routers.stalwart.entrypoints=https
- traefik.http.routers.stalwart.tls.certresolver=le
- traefik.http.routers.stalwart.service=stalwart
- traefik.http.services.stalwart.loadbalancer.server.port=8080
# jmap
- traefik.tcp.routers.jmap.rule=HostSNI(`*`)
- traefik.tcp.routers.jmap.entrypoints=https
- traefik.tcp.routers.jmap.tls.passthrough=true
- traefik.tcp.routers.jmap.service=jmap
- traefik.tcp.services.jmap.loadbalancer.server.port=443
- traefik.tcp.services.jmap.loadbalancer.proxyProtocol.version=2
# esmtp
- traefik.tcp.routers.esmtp.rule=HostSNI(`*`)
- traefik.tcp.routers.esmtp.entrypoints=esmtp
- traefik.tcp.routers.esmtp.tls.passthrough=true
- traefik.tcp.routers.esmtp.service=esmtp
- traefik.tcp.services.esmtp.loadbalancer.server.port=465
- traefik.tcp.services.esmtp.loadbalancer.proxyProtocol.version=2
# imap-ssl
- traefik.tcp.routers.imap-ssl.rule=HostSNI(`*`)
- traefik.tcp.routers.imap-ssl.entrypoints=imap-ssl
- traefik.tcp.routers.imap-ssl.tls.passthrough=true
- traefik.tcp.routers.imap-ssl.service=imap-ssl
- traefik.tcp.services.imap-ssl.loadbalancer.server.port=993
- traefik.tcp.services.imap-ssl.loadbalancer.proxyProtocol.version=2
# sieve
- traefik.tcp.routers.sieve.rule=HostSNI(`*`)
- traefik.tcp.routers.sieve.entrypoints=sieve
- traefik.tcp.routers.sieve.tls.passthrough=true
- traefik.tcp.routers.sieve.service=sieve
- traefik.tcp.services.sieve.loadbalancer.server.port=4190
- traefik.tcp.services.sieve.loadbalancer.proxyProtocol.version=2
networks:
proxy:
ipv4_address: 172.18.0.21
networks:
proxy:
external: true
services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
# Mailserver
- "465:465" # ESMTP submission, implicit TLS
- "993:993" # IMAP4 secure, implicit TLS
- "4190:4190" # sieve
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
- ./traefik:/etc/traefik
networks:
proxy:
ipv4_address: 172.18.0.20
environment:
- CLOUDFLARE_EMAIL=MAIL
- CLOUDFLARE_DNS_API_TOKEN=TOKEN
certdumper:
image: ghcr.io/kereis/traefik-certs-dumper:latest
volumes:
- ./letsencrypt:/traefik:ro
- ./letsencrypt/dumped:/output:rw
networks:
proxy:
name: proxy
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
gateway: 172.18.0.1
global:
checkNewVersion: true
sendAnonymousUsage: false # true by default
api:
# Dashboard
#
# Optional
# Default: true
#
dashboard: true
providers:
docker:
exposedByDefault: false
network: proxy
file:
# watch for dynamic configuration changes
directory: /etc/traefik
watch: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
priority: 1000
to: "https"
scheme: "https"
https:
address: ":443"
http:
tls:
certResolver: le
esmtp:
address: ":465"
proxyProtocol:
trustedIPs:
- 172.18.0.20
- 172.18.0.21
imap-ssl:
address: ":993"
proxyProtocol:
trustedIPs:
- 172.18.0.20
- 172.18.0.21
sieve:
address: ":4190"
proxyProtocol:
trustedIPs:
- 172.18.0.20
- 172.18.0.21
certificatesResolvers:
le:
acme:
# tlschallenge: true
email: "mail@example.com"
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudflare
@seniyakk
Copy link

Hello @puRe1337.
Please help me to understand. Is it possible to config Stalwart - Traefik without using certdumper service?

@puRe1337
Copy link
Author

Hello @puRe1337. Please help me to understand. Is it possible to config Stalwart - Traefik without using certdumper service?

I don't think so at the moment, as Stalwart does not yet have an “external“ reader for acme.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment