Exposing apps and HTTPS
Routes
Section titled “Routes”For every app with an HTTP port, the App controller creates an HTTPRoute in the environment namespace. Its hostnames are the app’s custom domains plus <app>-<environment>.<baseDomain>. Processes with protocol: tcp (databases from templates) get a cluster-internal Service only.
Without platform.baseDomain and platform.gateway, apps are reachable only inside the cluster.
Listeners
Section titled “Listeners”When clusterIssuer is set, Kuben owns the listeners of the Gateway named in KubenConfig.spec.gateway. That Gateway must therefore be dedicated to Kuben. Kuben maintains:
http(port 80): only the platform’s redirect route and cert-manager’s challenge routes may attach. Every other request is redirected to HTTPS.- One HTTPS listener per hostname, named
h-<hash>, with the certificate Secretkuben-tls-<hash>. A hostname admits routes only from the namespace that claimed it first. - Optionally one wildcard listener
httpsfor*.<baseDomain>, whenwildcardTlsSecretis set. All generated hostnames then share it.
The Gateway gets the annotation cert-manager.io/cluster-issuer, and cert-manager’s gateway-shim issues a certificate for every listener.
A minimal Gateway
Section titled “A minimal Gateway”Kuben fills in the listeners; you only create the shell:
apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata: name: kuben namespace: kuben-systemspec: gatewayClassName: traefik # or eg (Envoy Gateway), cilium listeners: - name: http protocol: HTTP port: 80Then reference it in the chart: --set platform.gateway=kuben-system/kuben.
A ClusterIssuer that solves HTTP-01 through that Gateway
Section titled “A ClusterIssuer that solves HTTP-01 through that Gateway”apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: letsencryptspec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: ops@example.com privateKeySecretRef: name: letsencrypt-account solvers: - http01: gatewayHTTPRoute: parentRefs: - kind: Gateway name: kuben namespace: kuben-system sectionName: httpcert-manager needs its Gateway API support switched on: helm upgrade cert-manager … --set config.enableGatewayAPI=true.
Wildcard certificate
Section titled “Wildcard certificate”With many apps, one listener per generated hostname runs into the listener cap. Issue a DNS-01 Certificate for *.<baseDomain> whose name equals the Secret name you put in wildcardTlsSecret; cert-manager then leaves it alone instead of trying HTTP-01 on the wildcard listener.
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: apps-wildcard # == secretName namespace: kuben-systemspec: secretName: apps-wildcard dnsNames: ["*.apps.example.com"] issuerRef: kind: ClusterIssuer name: letsencrypt-dns # a DNS-01 issuerhelm upgrade kuben oci://ghcr.io/teamtem-dev/charts/kuben -n kuben-system --reuse-values \ --set platform.wildcardTlsSecret=apps-wildcardHonest limits
Section titled “Honest limits”- A Gateway holds at most 64 listeners; Kuben uses at most 60. Beyond that, use the wildcard listener for generated hosts. ListenerSet support (experimental in Gateway API) is on the roadmap.
- TLS termination happens at your Gateway controller. Kuben only configures it; it never handles app traffic.
- One Gateway per Kuben installation. The chart’s optional
routefor the console can use the same Gateway.
Status
Section titled “Status”Each app reports its exposure in the Exposed condition:
| Reason | Meaning |
|---|---|
RouteApplied |
the HTTPRoute exists and is attached |
NoGateway |
KubenConfig.spec.gateway is unset or the Gateway does not exist |
NoHostname |
the app has no domain and no base domain is configured |
GatewayAPIMissing |
the Gateway API CRDs are not installed |
The Check DNS button (GET …/apps/{app}/domains) tells you whether each hostname already points at the Gateway. See Custom domains and HTTPS for the user-facing flow.