Skip to content
kix /docs
Install the CLI

How-to guide Platform capabilities

Add TLS through a cluster issuer

Have Kix annotate an Ingress for cert-manager and create its TLS configuration from the cluster's selected issuer.

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
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
(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, with the Secret <instance>-tls.

Install cert-manager and configure the issuer:

clusters/test-doc-how-tos.nix
instances.cert-manager.cert-manager = {
package = packages.cert-manager;
};
# A Secret created outside Kix that holds the Cloudflare API token
# under the key `api-token`.
instances.cert-manager.cloudflare-api-token = {
package = packages.secret-ref;
config.keys = [ "api-token" ];
};
instances.cert-manager.letsencrypt = {
package = packages.cluster-issuer;
deps.issuerCredentials = ref.cert-manager.cloudflare-api-token;
config.spec.acme = {
server = "https://acme-v02.api.letsencrypt.org/directory";
email = "[email protected]";
solvers = [
{
dns01.cloudflare.apiTokenSecretRef.key = "api-token";
selector.dnsZones = [ "example.com" ];
}
];
};
};

View source on GitHub ↗

The cluster-issuer package declares clusterIssuer as a default alias, so TLS-capable packages resolve it without per-application deps entries. Exactly one instance should answer clusterIssuer; give any other issuer, such as a staging one, its own aliases.

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

Configure the application hostname:

clusters/test-doc-how-tos.nix
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

cert-manager creates the <instance>-tls Secret in the Ingress’s namespace, which is where the Ingress reads it.