Skip to main content

Helm chart reference

The RapidMX server chart (oci://ghcr.io/rapidmx/charts/server) installs the RapidMX server together with everything it depends on. The Kubernetes, single server and AWS options all use it; the two installers just choose its values for you. This page is the full reference: how the pieces fit, what the chart expects to find in the cluster, the behaviour behind the less obvious values, and a table of every value with its default.

TL;DR​

helm upgrade --install --create-namespace --namespace rapidmx rapidmx \
oci://ghcr.io/rapidmx/charts/server --version 1.0.0-beta.43 \
--set global.domain=example.com \
--set global.jwt.secret="$(openssl rand -hex 32)" \
--set global.mailIngestSecret="$(openssl rand -hex 32)"

Architecture​

ComponentWhat it doesCreated by
RapidMX serverThe web app, admin console, REST API, Exchange ActiveSync and MAPI (as plugins). A Deployment named <fullname>-services behind a Service of the same name on port 80.This chart
auth-serverSign-in, accounts, two-factor, app passwords. Served on authserver.host.authserver subchart (oci://ghcr.io/rapidrest/charts/auth-server)
MongoDBThe database for both the server and the auth-server. PostgreSQL can replace it.Bitnami mongodb subchart
RedisCache, events and the rspamd classifier's statistics.Bitnami redis subchart
rspamdSpam scoring, and learning from users' junk reports.This chart
ClamAVVirus scanning.This chart
Postfix and postfix-bridgeInbound and outbound SMTP on port 25, DKIM signing.postfixBridge subchart (oci://ghcr.io/rapidmx/charts/postfix-bridge)
coturnTURN relay for video calls, on the node's own network.This chart
Gateway, HTTPRoutes, Issuer, CertificatesHTTPS for host, autodiscover.<domain> and authserver.host, with Let's Encrypt certificates.This chart and the auth-server subchart

<fullname> is the release name, followed by -server unless the release name already contains server. A release named rapidmx gives rapidmx-server; a release named rapidmx-server gives rapidmx-server.

The public Gateway answers 404 for /internal. The MTA hand-off API is reached only inside the cluster, through the <fullname>-services Service, or through the optional internal load balancer (mail.ingestService) for ses-bridge.

Prerequisites​

  • Kubernetes with a default StorageClass (or global.storageClass)
  • Helm 3.8 or later. Upgrades with --reset-then-reuse-values need Helm 3.14 or later.
  • A Gateway API controller and a GatewayClass (default envoy). The chart's response compression policy is specific to Envoy Gateway.
  • cert-manager with config.enableGatewayAPI=true, while global.gateway.tls is on
  • A way to expose a LoadBalancer Service on port 25, for Postfix
  • With global.openbao.enabled: an OpenBao the chart can reach, and External Secrets. The chart installs neither. See Secrets and OpenBao.
  • metrics-server, for the live figures on the admin console's Diagnostics page (k3s includes it). Optional.

Installing and uninstalling​

Install with the TL;DR command or the Kubernetes guide. To install from a checkout of the server repository instead of GHCR:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm dep up ./helm
helm upgrade --install --create-namespace --namespace rapidmx rapidmx ./helm --set global.domain=example.com ...

Upgrade as described in Upgrading. helm uninstall leaves the data volumes behind on purpose, see Uninstalling.

helm test rapidmx -n rapidmx runs a pod that fetches the <fullname>-services Service.

Configuration and installation details​

Host names​

global.domain is the deployment's mail domain (for example example.com). Everything else follows from it unless you override it:

WhatValueDefault
The serverhostmail.<global.domain>
The auth-serverauthserver.hostauth.<global.domain>
Autodiscoverfixedautodiscover.<global.domain>, served by the same route and certificate as host
Postfix's MX host namepostfixBridge.hostnamemail.<global.domain>
Domains Postfix knows at startpostfixBridge.domains<global.domain>
JWT audience and issuerglobal.jwt.audience, global.jwt.issuerthe domain, and the auth host

The auth-server subchart can't see the top-level host, so it is told the server's host through global.serverHost. If you change host, set global.serverHost to the same name. The render fails when the two differ, because the auth-server's Return to App button would point at a host this release doesn't serve.

The chart also sets the public addresses of the plugins whose pages it serves on host: mail__autodiscover__public_url (https://<host>), mail__booking__public_url (https://<host>/book) and mail__videoconf__public_url (https://<host>/meet). A value an administrator saves in a plugin's settings in the admin console wins over these; an empty saved value doesn't.

Secrets​

Without OpenBao (the default), the chart needs two secrets from you:

  • global.jwt.secret, the JWT secret shared with the bundled auth-server. The render fails without it, because each side would otherwise generate its own and every sign-in would be rejected.
  • global.mailIngestSecret, shared with postfix-bridge. The render fails when it's empty or the old development placeholder. The server warns at startup when it's shorter than 16 characters.

Pass the same values on every upgrade, or use --reset-then-reuse-values.

The cookie, session and escrow audit secrets are generated on install, stored in the <fullname>-service-secrets Secret and read back on every upgrade. That needs cluster access, so rendering without it (helm template, Argo CD or Flux, --dry-run) fails until you set global.secrets.cookies, global.secrets.sessions and mail.escrow.auditHmacKey explicitly, or point global.secrets.existingSecret at a Secret you manage. The same goes for the generated rspamd controller password and coturn secret.

The escrow audit key can never change silently: if you set mail.escrow.auditHmacKey to something other than the stored value, the render fails and tells you how to read the stored one.

With global.openbao.enabled, all of these live in OpenBao instead. See Secrets and OpenBao.

Gateway and TLS​

By default the chart creates a Gateway named <fullname>-gateway with global.gateway.className, and an Issuer named <fullname>-issuer that gets Let's Encrypt certificates over HTTP-01 through that Gateway. The certificate for host covers autodiscover.<global.domain> too. Certificates are only requested for a host that isn't localhost or a .local/.localhost name.

  • global.gateway.tls=false serves plain HTTP and issues no certificates.
  • global.gateway.httpRedirect (on by default) redirects plain HTTP to HTTPS on a Gateway this chart creates, while still answering the HTTP-01 challenge. Turn it off when something in front terminates TLS and forwards plain HTTP to the Gateway, or every request loops.
  • To use a Gateway you already have, set global.gateway.name and global.gateway.namespace. The route names no listener, so it attaches to every listener that accepts the host. With TLS on, the chart renders a ReferenceGrant that lets that Gateway read each <host>-tls-cert Secret; the Gateway needs an HTTPS listener per host that terminates TLS with it.
  • global.gateway.tlsTermination=pod passes TLS through to the server pod instead, with the same certificate. The pod only reads it at startup, so restart it within the 15 days between a renewal and the old certificate's expiry.
  • With Envoy Gateway, a BackendTrafficPolicy compresses the API's JSON and the pages' HTML (brotli, else gzip). global.gateway.compression.enabled: auto renders it when the cluster has that API.

Mail transport​

The bundled postfix-bridge (postfixBridge.create) receives mail on port 25 and relays the server's outgoing mail. The render fails for a public host when postfixBridge.hostname is left as a placeholder, or when postfixBridge.domains is still example.com. To let Postfix present the certificate the chart already issues for host rather than ask Let's Encrypt for a second one, set postfixBridge.tls.existingSecret to <host>-tls-cert, as the single-server installer does.

For Amazon SES, set mail.transport.provider=ses with postfixBridge.create=false; the render fails if both transports are on. See Mail transport.

mail.trustedAuthservId is the authserv-id of the Authentication-Results header your inbound MTA stamps, which the server trusts to say whether a sender's DKIM signature verified. With the bundled Postfix it defaults to postfixBridge.hostname. With any other MTA you must set it, or no sender is ever DKIM-verified: members-only distribution lists drop all mail, list and forward copies get a rewritten From, and forwarded invites are refused.

The bundled auth-server sends its codes by e-mail over SMTP, configured by global.smtp (the subchart can't read mail.*). The defaults send through the bundled Postfix.

Storage​

VolumeHoldsValue
<fullname>-dkim-keysDKIM private keys, written by the server and read by Postfixmail.dkim.storage
<fullname>-blob-dataMessage bodies, attachments, contact photos and uploaded plugin packs (only with mail.blob.backend=local)mail.blob.storage
<fullname>-pki-dataThe local encryption CA's key, and the signing-certificate enrollment statemail.pki.storage
mongodbThe server's and the auth-server's databasesmongodb.persistence

With mail.storage.keepOnUninstall (on by default), the first three claims carry helm.sh/resource-policy: keep, and so does the bundled MongoDB's, so helm uninstall can't destroy mail. A claim's storage class can't change once it exists; changing global.storageClass only applies to new claims.

Postfix signs with the keys on the DKIM volume, so with the default ReadWriteOnce the server and Postfix pods must run on the same node.

The bundled Redis keeps no data on disk (redis.master.persistence.enabled is off). Only the rspamd classifier's learned statistics are lost if the Redis pod is deleted.

Replicas​

The chart runs one server replica, because its DKIM, blob and PKI volumes are ReadWriteOnce. With more than one replica and any of those still ReadWriteOnce, the render fails. With only ReadWriteOnce volumes the Deployment uses the Recreate strategy, so an upgrade has a short outage. See Scaling.

Client addresses​

global.trustedProxies lists the addresses whose X-Forwarded-For the server believes, for rate limits, Basic sign-in failure counts and the audit log. The default private ranges are only safe where the Gateway sees the real client address (PROXY protocol, or externalTrafficPolicy: Local). Behind a load balancer that source-NATs to a private address, narrow it to the Gateway's pod range.

Diagnostics permissions​

global.diagnostics.rbac.create adds a read-only Role and RoleBinding (pods, persistent volume claims and pod metrics, in the release namespace only) to the chart's ServiceAccount, for the admin console's Diagnostics page. The auth-server subchart gets the same. Turned off, those parts of the page say Kubernetes denied the request. See Monitoring.

Signing certificates​

mail.signingEnrollment.backend chooses how mailboxes get S/MIME signing certificates. auto picks rfc8823 (automated issuance from an RFC 8823 certificate authority at mail.signingEnrollment.directoryUrl) for a real domain, and manual (an administrator uploads each certificate) for localhost or a domain ending in .local, .localhost, .test or .invalid. Any other value fails the render, as does a non-https:// directoryUrl once resolved to rfc8823. rfc8823 needs inbound mail and DKIM signing working. See Encryption and certificates.

Spam filter and TURN relay​

rspamd's controller password and coturn's secret are generated once and kept in the <fullname>-rspamd and <fullname>-coturn Secrets. Spam and virus filtering covers learning from reports, and Video calls: the TURN relay covers coturn.

Settings not exposed as values​

service.config is rendered into the server's ConfigMap as environment variables, so any server setting can be set there with its __-separated name, for example --set service.config.mail__dns__resolver=doh-dnssec. See Server configuration. A value set there for cookie_secret, session__secret or mail__escrow__audit_hmac_key counts as explicit and is used instead of a generated one.

Parameters​

Values are literal, as in values.yaml. Many are Helm templates rendered against the release.

NameDescriptionValue
hostThe host name the server is served atmail.{{ dig "domain" "localhost" (.Values.global | default dict) }}
environmentNODE_ENV of the server. Anything but production trusts localhost:3000 for CORS and starts Node with the inspector on 127.0.0.1:9229.production
global.cache.enabledConfigure Redis as the cache, events and logs datastorestrue
global.cache.urlRedis URLredis://redis-master
global.certmanager.emailLet's Encrypt account address of the chart's Issueradmin@{{ tpl $.Values.global.domain . }}
global.certmanager.nameIssuer name. The chart creates the Issuer only when this is <fullname>-issuer in the release namespace.'{{ include "rrst.fullname" . }}-issuer'
global.certmanager.namespaceIssuer namespace'{{ .Release.Namespace }}'
global.corsHostsBrowser origins allowed credentialed cross-origin calls, shared with the auth-server (also its allowed return_to origins). Each service adds its own host.["mail.{{ tpl (toString .Values.global.domain) . }}","auth.{{ tpl (toString .Values.global.domain) . }}"]
global.database.typemongo, or sql for PostgreSQLmongo
global.domainThe mail domaindomain.local
global.serverHostThe server's host, for the auth-server subchart. Empty: mail.<global.domain>. Set it together with host.''
global.gateway.nameThe Gateway the routes attach to. The chart creates it when it is <fullname>-gateway in the release namespace.'{{ include "rrst.fullname" . }}-gateway'
global.gateway.namespaceThe Gateway's namespace'{{ .Release.Namespace }}'
global.gateway.classNameGatewayClass of a Gateway the chart createsenvoy
global.gateway.hstsSend Strict-Transport-Security and allow only https:// originstrue
global.gateway.tlsIssue certificates and serve HTTPStrue
global.gateway.httpRedirectRedirect HTTP to HTTPS on a Gateway the chart createstrue
global.gateway.tlsTerminationgateway, or pod to pass TLS through to the server podgateway
global.gateway.tlsExtraDnsNamesExtra names on the certificate, with pod-terminated TLS[]
global.gateway.compression.enabledEnvoy Gateway response compression: auto, true or falseauto
global.gateway.compression.minContentLengthSmallest response compressed, in bytes1024
global.jwt.audienceJWT aud{{ include "rrst.render" (dict "value" .Values.global.domain "context" .) }}
global.jwt.issuerJWT iss{{ if hasKey .Values "authserver" }}{{ include "rrst.render" (dict "value" (.Values.authserver.host | default (printf "auth.%s" (toString .Values.global.domain))) "context" .) }}{{ else }}{{ include "rrst.render" (dict "value" .Values.host "context" .) }}{{ end }}
global.jwt.expiresInToken lifetime1 hour
global.jwt.secretJWT secret shared with the auth-server. Required without OpenBao.''
global.externalSecrets.enabledUse External Secrets to deliver OpenBao-held secrets (with global.openbao.enabled)true
global.externalSecrets.refreshIntervalHow often External Secrets re-reads the vault1m
global.logs.levelLog level. Not read by this chart's templates; the server's level is its logger__level setting (see Server configuration).info
global.openbao.enabledKeep the release's secrets in OpenBaofalse
global.openbao.addressOpenBao's addresshttp://openbao.openbao.svc:8200
global.openbao.kvMountThe kv v2 mountsecret
global.openbao.secretsPathThe path of this release's secrets. Empty: <fullname>/secrets.''
global.openbao.auth.methodtoken or kubernetestoken
global.openbao.auth.tokenSecretSecret holding a token that may read the secrets. Empty: <fullname>-openbao-eso.''
global.openbao.auth.tokenSecretKeyKey of the token in that Secrettoken
global.openbao.auth.kubernetes.mountPathKubernetes auth mountkubernetes
global.openbao.auth.kubernetes.roleOpenBao role bound to the ServiceAccount. Required with kubernetes.''
global.openbao.auth.kubernetes.serviceAccountServiceAccount External Secrets authenticates asdefault
global.secrets.existingSecretA Secret you manage with cookie_secret, session__secret and mail__escrow__audit_hmac_key, used instead of the generated one''
global.secrets.cookiesCookie secret. Empty: generated once and kept.''
global.secrets.sessionsSession secret. Empty: generated once and kept.''
global.diagnostics.rbac.createCreate the read-only Role for the Diagnostics pagetrue
global.serviceAccount.createCreate a ServiceAccount per charttrue
global.serviceAccount.nameServiceAccount name. Leave empty.''
global.serviceAccount.annotationsServiceAccount annotations, for example an IRSA role ARN{}
global.smtp.hostThe auth-server's SMTP hostpostfix
global.smtp.portSMTP port25
global.smtp.secureImplicit TLSfalse
global.smtp.ignoreTLSNever use STARTTLStrue
global.smtp.requireTLSRequire STARTTLSfalse
global.smtp.fromSender of the auth-server's e-mail. Empty: noreply@<global.domain>.''
global.storageClassStorage class of the DKIM, blob and PKI volumes. Empty: the cluster default.''
global.trustedProxiesAddresses whose X-Forwarded-For is believed["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16","fc00::/7"]
mongodb.createInstall the bundled MongoDBtrue
mongodb.architectureMongoDB architecturestandalone
mongodb.fullnameOverrideMongoDB's name, and its hostmongodb
mongodb.auth.enabledMongoDB authentication. Enabling it needs an empty data directory.false
mongodb.networkPolicy.allowExternalAdmit every pod. Off: only pods labelled mongodb-client.false
mongodb.persistence.resourcePolicyKeep the claim on uninstallkeep
mongodb.resourcesPresetBitnami resources presetnone
mongodb.resources.requests.cpuCPU request500m
mongodb.resources.requests.memoryMemory request512Mi
mongodb.resources.requests.ephemeral-storageEphemeral storage request50Mi
mongodb.updateStrategy.typeUpdate strategy. Recreate, because one mongod owns the data directory.Recreate
mongodb.livenessProbe.periodSecondsLiveness probe period60
mongodb.livenessProbe.timeoutSecondsLiveness probe timeout15
mongodb.livenessProbe.failureThresholdLiveness probe failures3
mongodb.readinessProbe.periodSecondsReadiness probe period30
mongodb.readinessProbe.timeoutSecondsReadiness probe timeout10
mongodb.readinessProbe.failureThresholdReadiness probe failures3
postgresql.createInstall the bundled PostgreSQL instead of MongoDBfalse
postgresql.architecturePostgreSQL architecturestandalone
postgresql.fullnameOverridePostgreSQL's name, and its hostpostgresql
postgresql.auth.enablePostgresUserCreate the postgres user with a passwordfalse
postgresql.auth.databaseDatabase created on first startrrst_auth
postgresql.primary.networkPolicy.allowExternalAdmit every podfalse
postgresql.readReplicas.networkPolicy.allowExternalAdmit every podfalse
redis.createInstall the bundled Redistrue
redis.architectureRedis architecturestandalone
redis.auth.enabledRedis authenticationfalse
redis.fullnameOverrideRedis's nameredis
redis.master.resourcesPresetBitnami resources presetnone
redis.master.resources.requests.cpuCPU request100m
redis.master.resources.requests.memoryMemory request128Mi
redis.master.resources.requests.ephemeral-storageEphemeral storage request50Mi
redis.master.persistence.enabledKeep Redis data on a volumefalse
redis.replica.persistence.enabledKeep replica data on a volumefalse
redis.networkPolicy.enabledRender a NetworkPolicytrue
redis.networkPolicy.allowExternalAdmit every podfalse
service.image.registryServer image registryghcr.io
service.image.repositoryServer image repositoryrapidmx/server
service.image.tagServer image tag. Empty: the chart's appVersion.1.0.0-beta.43
service.replicasServer replicas. More than one needs ReadWriteMany storage, see Scaling.1
service.probeImageImage of the datastore wait init containers and helm testbusybox:1.37.0
service.resources.requests.cpuServer CPU request100m
service.resources.requests.memoryServer memory request512Mi
service.datastores.mongodb.acl.nameMongoDB database of the access control listsrrst_acls
service.datastores.mongodb.acl.hostIts host. Empty: mongodb.fullnameOverride.''
service.datastores.mongodb.mongo.nameMongoDB database of everything elserrst_auth
service.datastores.mongodb.mongo.hostIts host. Empty: mongodb.fullnameOverride.''
service.datastores.postgresql.namePostgreSQL databasepostgres
service.datastores.postgresql.hostIts host. Empty: postgresql.fullnameOverride.''
service.config.logsServer setting logstrue
service.config.metricsServer setting metricstrue
service.config.releaseNotesServer setting releaseNotestrue
service.config.mail__auth_server_urlThe auth-server's URL'{{ include "rapidmx.authServerURL" . }}'
service.config.system__plugins__uploads__enabledFrom plugins.uploads.enabled'{{ .Values.plugins.uploads.enabled }}'
service.config.system__plugins__uploads__max_bytesFrom plugins.uploads.maxBytes'{{ int64 .Values.plugins.uploads.maxBytes }}'
service.config.mail__basic_auth__enabledFrom mail.basicAuth.enabled'{{ .Values.mail.basicAuth.enabled }}'
service.config.mail__basic_auth__realmFrom mail.basicAuth.realm'{{ .Values.mail.basicAuth.realm }}'
service.config.mail__basic_auth__cache_ttl_msFrom mail.basicAuth.cacheTtlMs'{{ .Values.mail.basicAuth.cacheTtlMs }}'
service.config.mail__basic_auth__failure_limitFrom mail.basicAuth.failureLimit'{{ .Values.mail.basicAuth.failureLimit }}'
service.config.mail__internal__allow_forwardedAccept proxy headers on /internal/mta, with the internal ingest load balancer'{{ and .Values.mail.ingestService.enabled (ne (include "rrst.podTLS" .) "true") }}'
service.config.mail__security__trusted_authserv_idFrom mail.trustedAuthservId'{{ include "rapidmx.trustedAuthservId" . }}'
service.config.mail__dns__mx_hostnameThe MX host name in the DNS checklist{{ .Values.mail.mxHostname | default (include "rrst.render" (dict "value" .Values.postfixBridge.hostname "context" .)) }}
service.config.mail__videoconf__turn__urlThe TURN URL given to the Meet plugin'{{ include "rapidmx.coturnURL" . }}'
service.config.mail__autodiscover__public_urlAutodiscover's public URL'{{ include "rapidmx.serverURL" . }}'
service.config.mail__booking__public_urlBooking pages' public URL'{{ include "rapidmx.serverURL" . }}/book'
service.config.mail__videoconf__public_urlMeet's public join URL'{{ include "rapidmx.serverURL" . }}/meet'
service.config.mail__scan__spam__rspamd__urlrspamd's scan workerhttp://rspamd:11333
service.config.mail__scan__spam__rspamd__controller_urlrspamd's controllerhttp://rspamd:11334
service.config.mail__scan__spam__learn__enabledFrom mail.rspamd.learn.enabled'{{ .Values.mail.rspamd.learn.enabled }}'
service.config.mail__scan__av__clamav__hostClamAV hostclamav
service.config.mail__scan__av__clamav__portClamAV port3310
service.config.mail__pki__signing_enrollment__backendResolved from mail.signingEnrollment.backend'{{ include "rapidmx.signingEnrollmentBackend" . }}'
service.config.mail__pki__rfc8823__directory_urlFrom mail.signingEnrollment.directoryUrl'{{ include "rrst.render" (dict "value" .Values.mail.signingEnrollment.directoryUrl "context" .) }}'
service.config.mail__pki__rfc8823__contact_emailFrom mail.signingEnrollment.contactEmail'{{ include "rapidmx.signingEnrollmentContactEmail" . }}'
service.terminationGracePeriodSecondsPod termination grace period60
service.preStopSleepSecondsSleep before stopping, while the pod leaves the Gateway's endpoints10
service.podSecurityContext.runAsNonRootPod security contexttrue
service.podSecurityContext.runAsUserPod user1000
service.podSecurityContext.runAsGroupPod group1000
service.podSecurityContext.fsGroupVolume group1000
service.podSecurityContext.fsGroupChangePolicyWhen volume ownership is changedOnRootMismatch
service.podSecurityContext.seccompProfile.typeSeccomp profileRuntimeDefault
service.securityContext.allowPrivilegeEscalationContainer security contextfalse
service.securityContext.capabilities.dropDropped capabilities["ALL"]
service.startupProbe.httpGet.pathStartup probe path/api/status
service.startupProbe.httpGet.portStartup probe port3000
service.startupProbe.periodSecondsStartup probe period10
service.startupProbe.failureThresholdStartup probe failures (90 x 10 s = 15 minutes)90
service.livenessProbe.httpGet.pathLiveness probe path/api/status
service.livenessProbe.httpGet.portLiveness probe port3000
service.livenessProbe.periodSecondsLiveness probe period30
service.livenessProbe.timeoutSecondsLiveness probe timeout5
service.livenessProbe.failureThresholdLiveness probe failures22
authserver.createInstall the bundled auth-servertrue
authserver.mongodb.networkPolicy.allowExternalThe subchart's copy of mongodb.networkPolicy.allowExternal. Keep identical.false
authserver.mongodb.persistence.resourcePolicyThe subchart's copy of mongodb.persistence.resourcePolicykeep
authserver.postgresql.primary.networkPolicy.allowExternalThe subchart's copyfalse
authserver.postgresql.readReplicas.networkPolicy.allowExternalThe subchart's copyfalse
authserver.service.config.auth__allowRegistrationLet anyone register an accountfalse
authserver.service.config.auth__requireMFARequire two-factor sign-in for everyonefalse
authserver.service.config.auth__app_password__enabledApp passwords, which Outlook and ActiveSync sign in withtrue
authserver.service.config.app_urlWhere the account page's Return to App button goes'{{ include "rrst.appURL" . }}'
authserver.service.config.auth__cookie__access__domainCookie domain of the access token'.{{ .Values.global.domain }}'
authserver.service.config.auth__cookie__refresh__domainCookie domain of the refresh token'.{{ .Values.global.domain }}'
authserver.service.config.site_settings__iconUrlSign-in page icon (seeds once)'{{ include "rrst.appURL" . }}/images/logo.png'
authserver.service.config.site_settings__logoUrlSign-in page logo (seeds once)'{{ include "rrst.appURL" . }}/images/wordmark.png'
authserver.service.config.site_settings__siteTitleSign-in page title (seeds once)"RapidMX"
authserver.service.config.smtp_config__hostFrom global.smtp.host'{{ .Values.global.smtp.host }}'
authserver.service.config.smtp_config__portFrom global.smtp.port'{{ .Values.global.smtp.port }}'
authserver.service.config.smtp_config__secureFrom global.smtp.secure'{{ .Values.global.smtp.secure }}'
authserver.service.config.smtp_config__ignoreTLSFrom global.smtp.ignoreTLS'{{ .Values.global.smtp.ignoreTLS }}'
authserver.service.config.smtp_config__requireTLSFrom global.smtp.requireTLS'{{ .Values.global.smtp.requireTLS }}'
authserver.service.config.templates__from__emailSender of the auth-server's e-mail{{ .Values.global.smtp.from | default (printf "noreply@%s" (tpl (toString .Values.global.domain) .)) }}
authserver.service.extraEnvExtra environment variables of the auth-server, for example SMTP credentials from a Secret[]
postfixBridge.createInstall the bundled postfix-bridge and Postfixtrue
postfixBridge.nameOverridepostfix-bridge's chart namepostfix-bridge
postfixBridge.service.resources.limitspostfix-bridge's limits. null removes the subchart's memory limit.null
postfixBridge.postfix.image.tagPostfix image tag5.1.0
postfixBridge.postfix.resources.limitsPostfix's limits. null removes the subchart's memory limit.null
postfixBridge.ingestSecretIngest secret given to postfix-bridge'{{ .Values.global.mailIngestSecret }}'
postfixBridge.ingestSecretRef.nameSecret postfix-bridge reads the ingest secret from, with OpenBao{{ if .Values.global.openbao.enabled }}{{ ternary .Release.Name (printf "%s-server" .Release.Name) (contains "server" .Release.Name) }}-mail-ingest-secret{{ end }}
postfixBridge.ingestBaseUrlWhere postfix-bridge reaches /internal/mta{{ if and .Values.global.gateway.tls (eq .Values.global.gateway.tlsTermination "pod") (include "rrst.publicHost" (toString .Values.global.domain)) }}https{{ else }}http{{ end }}://{{ ternary .Release.Name (printf "%s-server" .Release.Name) (contains "server" .Release.Name) }}-services/internal/mta
postfixBridge.hostnamePostfix's public MX host namemail.{{ .Values.global.domain }}
postfixBridge.domainsComma-separated domains Postfix knows at start'{{ .Values.global.domain }}'
postfixBridge.tls.certManager.enabledHave cert-manager issue Postfix's certificate. Off: self-signed.true
postfixBridge.tls.certManager.issuerNameIssuer of Postfix's certificate{{ ternary .Release.Name (printf "%s-server" .Release.Name) (contains "server" .Release.Name) }}-issuer
postfixBridge.tls.certManager.issuerKindIssuer kindIssuer
postfixBridge.dkim.storage.existingClaimThe DKIM claim Postfix signs from{{ ternary .Release.Name (printf "%s-server" .Release.Name) (contains "server" .Release.Name) }}-dkim-keys
plugins.uploads.enabledLet an elevated administrator install a plugin by uploading its npm pack filetrue
plugins.uploads.maxBytesLargest pack accepted, in bytes52428800
mail.ingestSecretThe /internal/mta bearer secret'{{ .Values.global.mailIngestSecret }}'
mail.transport.providerpostfix or sespostfix
mail.transport.ses.regionSES region. Empty: the SDK's own resolution.''
mail.transport.ses.configurationSetSES configuration set''
mail.ingestService.enabledAdd an internal load balancer for /internal/mta, for ses-bridgefalse
mail.ingestService.typeIts Service typeLoadBalancer
mail.ingestService.annotationsIts annotations{"service.beta.kubernetes.io/aws-load-balancer-internal":"true"}
mail.ingestService.loadBalancerSourceRangesWho may reach it[]
mail.mxHostnameMX host name in the DNS checklist and the sender of system mail. Empty: postfixBridge.hostname.''
mail.basicAuth.enabledAccept app passwords (HTTP Basic) on /mapi and /Microsoft-Server-ActiveSynctrue
mail.basicAuth.realmThe realm a 401 namesRapidMX
mail.basicAuth.cacheTtlMsHow long a successful sign-in is remembered, in ms300000
mail.basicAuth.failureLimitFailed sign-ins per address and username in 15 minutes before a 42910
mail.trustedAuthservIdauthserv-id of trusted Authentication-Results. Empty with the bundled Postfix: postfixBridge.hostname.''
mail.relay.hostWhere the server relays outgoing mailpostfix
mail.relay.portRelay port25
mail.relay.tlsTLS to the relay (on/off)'off'
mail.relay.fromAddressEnvelope sender for the relay. Empty: mailer@<mxHostname or host>.''
mail.escrow.auditHmacKeyEscrow audit log key. Empty: generated once and kept. Never change it.''
mail.storage.keepOnUninstallKeep the DKIM, blob and PKI claims on helm uninstalltrue
mail.dkim.selectorDKIM selectormail
mail.dkim.autogenerateGenerate DKIM keystrue
mail.dkim.storage.storageClassNameDKIM volume storage class'{{ .Values.global.storageClass }}'
mail.dkim.storage.accessModeDKIM volume access modeReadWriteOnce
mail.dkim.storage.sizeDKIM volume size1Gi
mail.blob.backendlocal (a volume) or s3. With s3, also configure the server's mail__blob__* settings, see Scaling.local
mail.blob.storage.storageClassNameBlob volume storage class'{{ .Values.global.storageClass }}'
mail.blob.storage.accessModeBlob volume access modeReadWriteOnce
mail.blob.storage.sizeBlob volume size20Gi
mail.pki.storage.storageClassNamePKI volume storage class'{{ .Values.global.storageClass }}'
mail.pki.storage.accessModePKI volume access modeReadWriteOnce
mail.pki.storage.sizePKI volume size1Gi
mail.signingEnrollment.backendauto, rfc8823 or manualauto
mail.signingEnrollment.directoryUrlRFC 8823 ACME directory (must be https://)https://acme.castle.cloud/acme/directory
mail.signingEnrollment.contactEmailACME account contact. Empty: global.certmanager.email.''
mail.rspamd.image.registryrspamd image registrydocker.io
mail.rspamd.image.repositoryrspamd image repositoryrspamd/rspamd
mail.rspamd.image.tagrspamd image tag4.1.5
mail.rspamd.resources.requests.cpurspamd CPU request100m
mail.rspamd.resources.requests.memoryrspamd memory request256Mi
mail.rspamd.learn.enabledTeach rspamd from users' junk reportstrue
mail.rspamd.controller.passwordController password: 16 or more of letters, digits and . _ ~ -, with a letter. Empty: generated once and kept.''
mail.rspamd.controller.existingSecretSecret with key mail__scan__spam__rspamd__controller_password''
mail.rspamd.bayes.minLearnsMessages of each class learned before the classifier counts200
mail.rspamd.bayes.redis.servershost:port of the statistics Redis. Empty: from global.cache.url.''
mail.rspamd.bayes.redis.dbRedis database of the statistics1
mail.rspamd.bayes.redis.existingSecretSecret with the Redis password''
mail.rspamd.bayes.redis.existingSecretKeyKey of the passwordredis-password
mail.rspamd.bayes.extraConfigAdded to rspamd's local.d/classifier-bayes.conf''
mail.clamav.image.registryClamAV image registrydocker.io
mail.clamav.image.repositoryClamAV image repositoryclamav/clamav
mail.clamav.image.tagClamAV image tagstable
mail.clamav.image.pullPolicyClamAV pull policyAlways
mail.clamav.extraConfigLines appended to clamd.conf''
mail.clamav.resources.requests.cpuClamAV CPU request200m
mail.clamav.resources.requests.memoryClamAV memory request1Gi
mail.clamav.startupProbe.periodSecondsStartup probe period10
mail.clamav.startupProbe.failureThresholdStartup probe failures (about 10 minutes to load signatures)60
mail.clamav.readinessProbe.periodSecondsReadiness probe period10
mail.clamav.readinessProbe.timeoutSecondsReadiness probe timeout5
mail.clamav.readinessProbe.failureThresholdReadiness probe failures3
coturn.createInstall the TURN servertrue
coturn.image.registrycoturn image registrydocker.io
coturn.image.repositorycoturn image repositorycoturn/coturn
coturn.image.tagcoturn image tag4.18.0
coturn.hostnameName browsers reach coturn at. Empty: host.''
coturn.portTURN port (TCP and UDP)3478
coturn.externalIpThe node's public IPv4 address. Empty: discovered at start.''
coturn.relayPorts.minFirst UDP relay port49152
coturn.relayPorts.maxLast UDP relay port49252
coturn.auth.modesecret (a credential per participant) or credential (one shared)secret
coturn.auth.sharedSecretShared secret. Empty: generated once and kept.''
coturn.auth.usernameUser name, in credential moderapidmx
coturn.auth.passwordPassword, in credential mode. Empty: generated once and kept.''
coturn.auth.existingSecretA Secret you manage with the secret, or user name and password''
coturn.tls.enabledTURN over TLStrue
coturn.tls.portTURN over TLS port5349
coturn.tls.existingSecretkubernetes.io/tls Secret covering coturn.hostname. Empty: <host>-tls-cert.''
coturn.userQuotaAllocations one credential may hold at once25
coturn.totalQuotaAllocations in total. 0: no limit besides the relay ports.0
coturn.deniedPeerIpsRanges coturn refuses to relay to["0.0.0.0-0.255.255.255","10.0.0.0-10.255.255.255","100.64.0.0-100.127.255.255","127.0.0.0-127.255.255.255","169.254.0.0-169.254.255.255","172.16.0.0-172.31.255.255","192.0.0.0-192.0.0.255","192.168.0.0-192.168.255.255","198.18.0.0-198.19.255.255","240.0.0.0-255.255.255.255","::1","fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff","fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]
coturn.extraArgsMore turnserver arguments[]
coturn.nodeSelectorNode coturn runs on{}
coturn.tolerationscoturn tolerations[]
coturn.resources.requests.cpucoturn CPU request50m
coturn.resources.requests.memorycoturn memory request64Mi

Values the chart reads that have no default in values.yaml​

NameDescriptionValue
global.mailIngestSecretThe /internal/mta bearer secret shared with postfix-bridge. Required without OpenBao.unset
global.database.urlA database URL used instead of the bundled database'sunset
authserver.hostThe auth-server's host name (the subchart's default is auth.<global.domain>)unset
global.defaultAccountsAccounts the auth-server creates on first start (the subchart's default is one admin account with the admin role and a generated password)unset
postfixBridge.tls.existingSecretPostfix's own kubernetes.io/tls Secret, for example <host>-tls-certunset
openbao.pki.mountOpenBao PKI mount of the encryption CAunset
openbao.pki.roleIts issuing roleunset
openbao.pki.enabledLoad the PKI token Secret into the server podunset
openbao.pki.tokenSecretSecret whose mail__pki__openbao__token may sign and revoke on that roleunset
service.imagePullSecretImage pull Secret of the server podunset
service.specExtra fields added to the server's pod specunset
fullnameOverride, nameOverrideOverride the chart's resource namesunset

The subcharts have their own values: see the Bitnami MongoDB, PostgreSQL and Redis charts, the auth-server chart and the postfix-bridge chart.