feat: combine mail-plane charts into one umbrella Helm chart at helm/ - #36
Merged
Merged
Conversation
Move api-server, opendkim-server, raven-sasl-server and smtp-server out of
mail-infra/helm/ and into a single umbrella chart at the repo root, so the
whole outbound-mail stack installs as one release:
helm upgrade --install pingmailer ./helm -n <ns> -f my-values.yaml
Each service stays a self-contained subchart under helm/charts/ and can still
be installed on its own. Every subchart is gated by an `<name>.enabled` flag
so the stack can be rolled out piecemeal.
Subchart `name:` fields were renamed to match their directories
(silver-api-server -> api-server, etc.) so the umbrella values keys read
naturally. This is safe because every subchart pins fullnameOverride, so no
Service DNS name changes and Postfix's inet:opendkim-server:8891 /
inet:raven-sasl:12345 wiring is untouched.
Also:
- Add `hostAliases` to the api-server subchart. Callers pass `smtp_host` in the
/notify body and the api-server verifies the SMTP TLS certificate against
that name; the Service name `smtp-server` is not on the mail cert, and the
public mail hostname is unreachable from inside the cluster. Mapping the
cert-matching name to the SMTP ClusterIP fixes both. This previously existed
only as a live `oc patch` and was lost on every redeploy.
- Add helm/README.md: a full deployment guide covering prerequisites, required
values, DNS records, installing a subset, exposing SMTP, upgrades and
rollbacks, plus an OpenShift section (Route vs Ingress, restricted-v2 UID
assignment, ResourceQuota requirements, NodePort for SMTP) and an
end-to-end in-cluster mail test procedure.
- Generalise environment-specific references in chart comments so nothing
points at a particular cluster, namespace, domain or address.
certbot-server intentionally stays under mail-infra/helm/ — certificate
issuance has a separate lifecycle and is a prerequisite, not a component.
Verified: `helm lint` passes, the umbrella renders 19 resources, all four
subcharts still lint standalone, and a full uninstall/reinstall cycle on
OpenShift brought all four components up and delivered mail end-to-end
(XOAUTH2 auth via raven -> Postfix submission -> relayed out, status=sent).
Adds two workflows, both driven by publishing a GitHub Release (plus
workflow_dispatch for manual runs and a no-push dry run on PRs).
docker-release.yaml — builds the three images this repo owns and pushes each
to GHCR tagged with both `latest` and the release version:
- pingmailer-api-server (static Go binary, built for amd64, arm64,
arm/v7, ppc64le and s390x)
- silver-dkim (amd64, arm64)
- silver-smtp (amd64, arm64 — rebuilds Postfix from source, so
every extra platform is a full compile under QEMU)
silver-smtp also keeps its `rootless` tag moving, because that is what the
smtp-server subchart defaults to; without it a chart install would pin an
ageing image.
After pushing, the workflow inspects the manifest and fails if any requested
platform is missing. This guards a regression we actually hit: a tag was
published arm64-only and the cluster refused it with "no image found in image
index for architecture amd64" — better to fail at build time than at deploy.
`latest` moves only on a real release, never from a dispatch or a PR, so a
manual run cannot silently redirect consumers.
helm-release.yaml — lints the umbrella chart and every subchart standalone,
renders the example values, asserts the required-value guards still fire when
values are absent, then packages and pushes to
oci://ghcr.io/<owner>/charts/pingmailer.
The chart is versioned from the release tag via `helm package --version
--app-version`, so the chart, its appVersion and the image tags always agree
for a given release rather than drifting against Chart.yaml.
Also documents installing from the registry in helm/README.md.
raven-sasl is deliberately not built here — it lives in another repository and
is only consumed by this chart.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Combines the four mail-plane charts into a single umbrella Helm chart at
helm/, so the whole outbound-mail stack installs as one release instead of four:Each service stays a self-contained subchart and can still be installed on its own. Every subchart is gated by
<name>.enabled, so the stack can be rolled out piecemeal.Why the subcharts were renamed
Subchart
name:fields now match their directories (silver-api-server→api-server, etc.) so umbrella values keys read naturally (smtp-server.domainrather thansilver-smtp.domain).This is safe: every subchart pins
fullnameOverride, so no Service DNS name changes. Postfix'sinet:opendkim-server:8891andinet:raven-sasl:12345wiring is untouched.Also in this PR
hostAliasesadded to the api-server subchart. Callers passsmtp_hostin the/notifybody and the api-server verifies the SMTP TLS certificate against that name. The Service namesmtp-serveris not on the mail certificate, and the public mail hostname isn't reachable from inside the cluster (no hairpin). Mapping the cert-matching name to the SMTP ClusterIP fixes both. This previously existed only as a liveoc patchand was silently lost on every redeploy — every send failed while/notifystill returned202.helm/README.md— prerequisites, required values, DNS records, installing a subset, exposing SMTP, upgrade/rollback, troubleshooting, plus:restricted-v2UID assignment, ResourceQuota requirements, NodePort for SMTPEnvironment-specific references generalised across chart comments — no cluster, namespace, domain, or address from any particular deployment remains.
certbot-serverintentionally stays undermail-infra/helm/— certificate issuance has its own lifecycle and is a prerequisite, not a component of this chart.Notable gotchas documented
raven-sasl-serverpins UID 1001, whichrestricted-v2rejects at ReplicaSet level, so you get no pod and no pod events. Note thatpodSecurityContext: {}does not clear it — Helm merges empty maps into the subchart's populated map, so each key must be nulled individually.0.1.0tag exits demandingCERT_FILE/KEY_FILE;0.1.1is arm64-only.image.tag: ""resolves toappVersion(0.1.0), which is not what you want.POST /notifyreturns202 Email queued successfullyeven when the SMTP send later fails — never treat it as proof of delivery.hostAliasespins a ClusterIP, so it needs refreshing if the smtp-server Service is recreated.Verification
helm lintpasses on the umbrella and on all four subcharts standalone--set <name>.enabled=falsecorrectly drops a subchartdomain is required)status=sent,250 2.0.0 OK)Note for reviewers
Deployment-specific values are not committed.
.gitignoregainedmy-values.yaml/my-*-values.yamlfor local values files, which carry the OAuth client ID and sender allowlist.