# Stalwart Mail Server — Dezky PRODUCTION (bare-metal host, outside k3s)
#
# Topology (see host/README.md):
#   - Mail protocol ports bind directly on the host's public IP.
#   - Web/JMAP is served plaintext on 127-reachable :8080 and fronted by
#     Traefik (k3s) for mail.dezky.eu:443. Stalwart does NOT bind 80/443 —
#     those belong to Traefik.
#   - TLS for the mail-protocol ports uses a cert ISSUED BY cert-manager
#     (mail.dezky.eu) and copied here by stalwart/cert-sync.sh. Stalwart runs
#     no ACME of its own (80/443 are Traefik's).
#   - Storage is RocksDB on local disk — intentionally independent of the
#     in-cluster Postgres so mail keeps flowing regardless of cluster state.
#
# Reference: https://stalw.art/docs

[server]
hostname = "mail.dezky.eu"          # MUST match the IP's PTR/rDNS record

# ── Listeners ──────────────────────────────────────────────────────────────
# Mail protocols on the public IP; management/JMAP on internal 8080 only
# (firewall blocks 8080 from the world, allows the k3s pod CIDR + Traefik).
[server.listener]
"smtp"        = { bind = "[::]:25",   protocol = "smtp" }
"submission"  = { bind = "[::]:587",  protocol = "smtp", tls.implicit = false }
"submissions" = { bind = "[::]:465",  protocol = "smtp", tls.implicit = true }
"imap"        = { bind = "[::]:143",  protocol = "imap", tls.implicit = false }
"imaps"       = { bind = "[::]:993",  protocol = "imap", tls.implicit = true }
"sieve"       = { bind = "[::]:4190", protocol = "managesieve" }
# Internal HTTP: JMAP + WebAdmin + management API. Traefik terminates TLS for
# the public hostname and proxies here; platform-api (pod) calls it directly.
"http"        = { bind = "0.0.0.0:8080", protocol = "http" }

# ── Storage — RocksDB on local disk (host-isolated from the cluster) ────────
[store."rocksdb"]
type = "rocksdb"
path = "/opt/stalwart/data"
compression = "lz4"

[storage]
data = "rocksdb"
fts = "rocksdb"
blob = "rocksdb"
lookup = "rocksdb"
directory = "internal"

[directory."internal"]
type = "internal"
store = "rocksdb"

# ── TLS — cert issued by cert-manager, synced here by cert-sync.sh ──────────
# Until the first sync runs, install.sh drops a self-signed bootstrap cert so
# the TLS listeners can start. cert-sync replaces it with the real LE cert.
[certificate."default"]
cert = "%{file:/opt/stalwart/etc/tls/cert.pem}%"
private-key = "%{file:/opt/stalwart/etc/tls/key.pem}%"
default = true

# ── Authentication ─────────────────────────────────────────────────────────
# Fallback admin is what platform-api uses for Basic auth on the JMAP
# management API (STALWART_ADMIN_USER/PASSWORD on the platform-api side).
[authentication]
fallback-admin.user = "admin"
fallback-admin.secret = "$env{STALWART_ADMIN_PASSWORD}"

# ── Resolver ───────────────────────────────────────────────────────────────
# DNSSEC-aware system resolver. Mail deliverability depends on clean DNS.
[resolver]
type = "system"
preserve-intermediates = true
concurrency = 4

# ── Spam filtering — built-in filter ON in production ──────────────────────
[spam-filter]
enable = true

# ── Logging — journald captures stdout ─────────────────────────────────────
[tracer."stdout"]
type = "stdout"
level = "info"
ansi = false
enable = true

# ── Audit webhook → platform-api (via the public api ingress) ──────────────
# Stalwart on the host reaches platform-api through Traefik on the public
# hostname; HMAC-signed so a public endpoint is safe.
[webhook."audit-ingest"]
url = "https://api.dezky.eu/ingest/stalwart/webhook"
signature-key = "$env{STALWART_WEBHOOK_SECRET}"
events = [
    "auth.success",
    "auth.failure",
    "auth.banned",
    "account.created",
    "account.deleted",
    "account.password-changed",
    "message.rejected",
    "policy.rejection",
    "dkim.failure",
    "dmarc.failure",
    "spam.detected",
]
throttle = "1s"
