{{- /* config.json - the ONLY file Stalwart reads from disk, and the only part of its configuration this chart owns. It is exactly the DataStore object, with no wrapper: upstream's declarative deployment page states "It only needs to contain the DataStore object", and the reader confirms it - crates/store/src/registry/local.rs deserializes the whole file straight into the DataStore enum, which is internally tagged on "@type". Everything else (listeners, blob store, in-memory store, TLS objects, domains, cluster roles) is a JMAP object in the database and is created in the WebUI. WHY A CONFIGMAP AND NOT A SECRET: there is no credential in here. authSecret is a tagged sub-object with an EnvironmentVariable variant, so the password is referenced by NAME and arrives through the env (see the StatefulSet). That is what keeps checksum/config meaningful - Helm can hash this file because Helm can see all of it. The username is NOT a secret and cannot be made one: authUsername is a plain String on the object with no secret form, unlike authSecret. It is public here by necessity, not by oversight. */ -}} {{- $pg := .Values.dataStore.postgres -}} {{- $store := dict "@type" "PostgreSql" "host" (required "dataStore.postgres.host is required - without it Stalwart has no database, and a config.json that cannot be parsed or reached is the one case that does abort the start loudly" $pg.host) "port" (int $pg.port) "database" $pg.database "authUsername" $pg.username "authSecret" (dict "@type" "EnvironmentVariable" "variableName" (include "stalwart.env.dbPassword" .)) "useTls" $pg.tls.enable "allowInvalidCerts" $pg.tls.allowInvalidCerts "poolMaxConnections" (int $pg.poolMaxConnections) "timeout" (int $pg.timeoutMs) -}} {{- if not (kindIs "invalid" $pg.options) -}} {{- $_ := set $store "options" $pg.options -}} {{- end -}} apiVersion: v1 kind: ConfigMap metadata: name: {{ include "stalwart.fullname" . }}-configmap labels: app: {{ include "stalwart.fullname" . }} data: # Rendered through toPrettyJson from a dict rather than written as a JSON # literal: "timeout" is a Duration, which upstream's object encoding defines # as an INTEGER COUNT OF MILLISECONDS and which explicitly "does not accept a # string" - the serde impl deserializes it through u64::deserialize into # Duration::from_millis. A hand-written literal is where a "15s" creeps in, # and the server then refuses to parse the file at startup. Going through the # dict also means "port" and "poolMaxConnections" cannot come out quoted. config.json: | {{- toPrettyJson $store | nindent 4 }}