Install

DNS and TLS

Point a hostname at the ingress and let cert-manager issue the certificate.

DNS and TLS

The chart renders an nginx Ingress and asks cert-manager for a certificate. Neither of those can invent a hostname, so platform.host and your DNS records have to agree.

What platform.host has to match

platform.host is the public hostname of your API. The chart uses it in three places at once: the host on the Ingress rule, the name on the TLS certificate, and the base URL the platform hands to its own clients. There is no separate place to correct a mismatch, which is the point.

So the rule is simple. Whatever you set as platform.host must be the name that resolves to your cluster's ingress, and it must be the name your customers actually type. If you split the API and the web app onto separate hostnames, platform.host is the API one.

Point DNS at the ingress

Find the external address of your ingress controller:

kubectl -n ingress-nginx get svc ingress-nginx-controller

Take the EXTERNAL-IP from that output and create an A record for platform.host pointing at it. A wildcard A record for *.acme.com works too, and saves you a record per host if you plan to give the web app and the realtime stream their own names.

Do this before you install, or at least before you expect a certificate. cert-manager's default letsencrypt-prod issuer solves an HTTP-01 challenge, which means Let's Encrypt has to reach http://<platform.host>/.well-known/acme-challenge/... through your ingress. Until DNS resolves, the challenge cannot be served and the certificate stays pending. Nothing is broken at that point; the order is just waiting for a name that does not exist yet.

ingress.externalDNS is false by default, which assumes you manage that record by hand. Turn it on if you run external-dns and want the chart to annotate the Ingress for it.

The certificate

cert-manager does the issuing. The chart annotates each Ingress with cert-manager.io/cluster-issuer, taking the name from ingress.clusterIssuer (default letsencrypt-prod), and names a TLS Secret for the certificate to land in. A ClusterIssuer by that exact name has to already exist in the cluster: the chart does not create one.

Watch it arrive:

kubectl -n my-mvno get certificate
kubectl -n my-mvno describe certificate my-mvno-platform-tls

READY: True means you are done. A certificate stuck on False for more than a few minutes is almost always DNS: describe the Order and Challenge objects underneath it and the message will say so.

The ingress class comes from ingress.className, default nginx. The chart's Ingress objects are nginx plus cert-manager and nothing else, so a cluster running a different ingress controller needs that value changed, and a cluster running a Gateway API implementation instead is not a topology this chart renders.

App and realtime hosts

The web app and the realtime stream can have hostnames of their own:

--set ingress.hosts.app=app.acme.com \
--set ingress.hosts.realtime=rt.acme.com

If you enable either workload but leave its host empty, the chart renders no Ingress for it. That is deliberate rather than a bug: two Ingresses claiming the same host and the same path would collide, so a workload without its own hostname stays reachable inside the cluster only, on its Service name. Give it a host when you want it public, and add the DNS record to match.

platform.scheme

Leave platform.scheme at https.

Setting it to http is a local development escape hatch, and it does exactly what it sounds like: the chart drops the cert-manager annotation and the whole tls block from every Ingress, so nothing is encrypted and no certificate is issued. It also turns passkey sign-in off, because WebAuthn will not run over plain http on anything but localhost. Both of those are correct for a kind cluster on your laptop and wrong for anything a customer will ever reach.

Next: Verify your install.

Copyright © 2026