Skip to content

Add TLS through cluster issuers

When a package uses kix.expose, Kix can add TLS to its Ingress from the cluster’s clusterIssuer dependency. cert-manager then creates and renews the certificate Secret named by that Ingress.

This path requires an ingress-nginx provider and a ready ClusterIssuer. Gateway API listeners manage TLS separately and do not use this integration.

Declare the standard ingress options:

how-to/platform/exposure-app.nix (L21–L21)
options.ingress = kix.options.ingress;

View source on GitHub ↗

Add kix.expose to the package build and point it at the Service part:

how-to/platform/exposure-app.nix (L56–L56)
(kix.expose { service = "service"; })

View source on GitHub ↗

kix.expose has optional dependencies on ingressNginx and clusterIssuer. With ingress-nginx alone it emits an HTTP Ingress. When a ClusterIssuer is also available, it adds:

  • cert-manager.io/cluster-issuer with the selected issuer name.
  • An Ingress TLS entry for the configured host.
  • A Secret name of <instance>-tls unless the package supplies another tracked TLS Secret.

Install cert-manager and configure the issuer:

clusters/test-doc-how-tos.nix (L108–L130)
instances.cert-manager.cert-manager = {
package = packages.cert-manager;
};
instances.cert-manager.cluster-issuers = {
package = packages."cluster-issuers";
config = {
mainIssuer = "letsencrypt-production";
issuers = lib.mkForce {
letsencrypt-production = {
kind = "acme";
server = "https://acme-v02.api.letsencrypt.org/directory";
email = "[email protected]";
privateKeySecretName = "letsencrypt-production-account";
cloudflareSecret = {
name = "cloudflare-api-token";
key = "api-token";
};
dnsZones = [ "example.com" ];
};
};
};
};

View source on GitHub ↗

The cluster-issuers package declares clusterIssuer as a default alias, so TLS-capable packages resolve it without per-application deps entries.

See Configure cert-manager issuers for the credential and self-signed configurations.

Configure the application hostname:

clusters/test-doc-how-tos.nix (L134–L137)
instances.apps.web = {
package = webPackage;
config.ingress.host = "web.example.com";
};

View source on GitHub ↗

If config.ingress.host is null, kix.expose can derive <instance>.<cluster.domain> when the cluster sets cluster.domain. Set the host explicitly when DNS or certificate policy requires a particular name.

Check the cluster, then inspect the Ingress before deployment:

❱ kix check doc-how-tos
❱ kix build doc-how-tos --output json | jq '.[] | select(.kind == "Ingress") | {name: .metadata.name, annotations: .metadata.annotations, tls: .spec.tls}'

After deployment, verify the Certificate and Secret created by cert-manager:

❱ kubectl -n apps get certificate,secret
❱ kubectl -n apps describe certificate web-tls

The Ingress and its TLS Secret must be in the same namespace. Kix validates that constraint when a package passes a Secret resource to kix.expose.