Files
sbbb/base/stalwart/stalwart-config.yaml
Sienna Meridian Satterwhite 8662c79212 checkpoint: stalwart deploy, beam-design, migration scripts, config tweaks
Stalwart + Bulwark mail server deployment with OIDC, TLS cert, vault
secrets. Beam design service. Pingora config cleanup. SeaweedFS
replication fix. Kratos values tweak. Migration scripts for mbox/messages
/calendars from La Suite to Stalwart.
2026-04-06 17:52:30 +01:00

149 lines
4.8 KiB
YAML

apiVersion: v1
kind: ConfigMap
metadata:
name: stalwart-config
namespace: stalwart
data:
# DOMAIN_SUFFIX is replaced by sed at deploy time.
# Secrets (%{env:VAR}%) are injected via environment variables in the Deployment.
#
# Only LOCAL keys belong in this file (store.*, storage.*, server.*, directory.*,
# tracer.*, cluster.*, certificate.*, authentication.fallback-admin.*).
# Everything else (OIDC, DKIM, spam, etc.) is configured via the Stalwart
# web admin UI and stored in the database.
config.toml: |
# Force http.url to be read from this file (not the database).
config.local-keys.0000 = "store.*"
config.local-keys.0001 = "directory.*"
config.local-keys.0002 = "tracer.*"
config.local-keys.0003 = "server.*"
config.local-keys.0004 = "!server.blocked-ip.*"
config.local-keys.0005 = "!server.allowed-ip.*"
config.local-keys.0006 = "authentication.fallback-admin.*"
config.local-keys.0007 = "cluster.*"
config.local-keys.0008 = "config.local-keys.*"
config.local-keys.0009 = "storage.*"
config.local-keys.0010 = "certificate.*"
config.local-keys.0011 = "http.url"
config.local-keys.0012 = "http.use-x-forwarded"
# Expression-quoted public URL (inner single quotes required).
http.url = "'https://mail.DOMAIN_SUFFIX'"
http.use-x-forwarded = true
[server]
hostname = "mail.DOMAIN_SUFFIX"
max-connections = 1024
[server.listener."smtp"]
bind = ["0.0.0.0:25"]
protocol = "smtp"
[server.listener."submission"]
bind = ["0.0.0.0:587"]
protocol = "smtp"
tls.implicit = false
[server.listener."smtps"]
bind = ["0.0.0.0:465"]
protocol = "smtp"
tls.implicit = true
[server.listener."imap"]
bind = ["0.0.0.0:143"]
protocol = "imap"
tls.implicit = false
[server.listener."imaps"]
bind = ["0.0.0.0:993"]
protocol = "imap"
tls.implicit = true
[server.listener."jmap"]
bind = ["0.0.0.0:8080"]
protocol = "http"
[server.listener."managesieve"]
bind = ["0.0.0.0:4190"]
protocol = "managesieve"
[certificate."default"]
cert = "%{file:/etc/stalwart-tls/tls.crt}%"
private-key = "%{file:/etc/stalwart-tls/tls.key}%"
# ── Storage backends ─────────────────────────────────────────────────────
[store."postgresql"]
type = "postgresql"
host = "postgres-rw.data.svc.cluster.local"
port = 5432
database = "stalwart_db"
user = "stalwart"
password = "%{env:DB_PASSWORD}%"
timeout = "15s"
[store."postgresql".pool]
max-connections = 20
[store."s3"]
type = "s3"
bucket = "sunbeam-stalwart"
endpoint = "http://seaweedfs-filer.storage.svc.cluster.local:8333"
region = "us-east-1"
access-key = "%{env:S3_ACCESS_KEY}%"
secret-key = "%{env:S3_SECRET_KEY}%"
key-prefix = "v1/"
timeout = "60s"
[store."opensearch"]
type = "elasticsearch"
url = "http://opensearch.data.svc.cluster.local:9200"
index = "stalwart"
[store."redis"]
type = "redis"
urls = ["redis://valkey.data.svc.cluster.local:6379/7"]
# ── Storage role assignments ─────────────────────────────────────────────
[storage]
data = "postgresql"
blob = "postgresql"
fts = "opensearch"
lookup = "redis"
directory = "hydra"
# ── Directories (user stores) ──────────────────────────────────────────
# Internal directory for locally-managed accounts (admin, service accounts).
[directory."internal"]
type = "internal"
store = "postgresql"
# OIDC directory — validates Hydra-issued bearer tokens via userinfo.
# When a JMAP client presents a Bearer token, Stalwart calls Hydra's
# userinfo endpoint to map it to a user identity.
[directory."hydra"]
type = "oidc"
timeout = "15s"
endpoint.url = "http://hydra-public.ory.svc.cluster.local:4444/userinfo"
endpoint.method = "userinfo"
fields.email = "email"
fields.username = "email"
fields.full-name = "name"
# ── Authentication ───────────────────────────────────────────────────────
[authentication.fallback-admin]
user = "admin"
secret = "%{env:ADMIN_PASSWORD}%"
# ── Logging ──────────────────────────────────────────────────────────────
[tracer."stdout"]
type = "stdout"
level = "info"
ansi = false
enable = true