Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Custom Components

The components.custom.apps option lets you deploy your own applications alongside the built-in infrastructure components. Custom apps support Helm charts, typed Kubernetes resources, raw YAML, and optional Gateway API routing – all without writing a full component module.

Example: Helm chart deployment

Deploy an application using a Helm chart:

# In your cluster configuration
{ cataCharts, ... }:
{
  components.custom.apps.my-app = {
    namespace = "my-app";
    phase = "apps";

    helmCharts.my-app = {
      chart = cataCharts.my-app.chart;  # if registered in lib/charts.nix
      # or use an inline chart path
      namespace = "my-app";
      values = {
        replicas = 2;
        image.tag = "v1.2.3";
        ingress.enabled = false;  # use Gateway API instead
      };
    };
  };
}

The chart is rendered at Nix build time and deployed during the specified phase. The namespace is created automatically unless you set createNamespace = false.

Example: Resources with a Gateway route

Deploy raw Kubernetes resources and expose them via the Gateway API:

{ config, lib, ... }:
let
  labDomain = config.cluster.lab.domain;  # e.g., "homelab.test"
in
{
  components.custom.apps.whoami = {
    namespace = "whoami";
    phase = "apps";

    resources = {
      whoami-deployment = {
        apiVersion = "apps/v1";
        kind = "Deployment";
        metadata = {
          name = "whoami";
          namespace = "whoami";
        };
        spec = {
          replicas = 1;
          selector.matchLabels.app = "whoami";
          template = {
            metadata.labels.app = "whoami";
            spec.containers = [
              {
                name = "whoami";
                image = "traefik/whoami:v1.10";
                ports = [ { containerPort = 80; } ];
              }
            ];
          };
        };
      };

      whoami-service = {
        apiVersion = "v1";
        kind = "Service";
        metadata = {
          name = "whoami";
          namespace = "whoami";
        };
        spec = {
          selector.app = "whoami";
          ports = [
            {
              port = 80;
              targetPort = 80;
            }
          ];
        };
      };
    };

    gateway = {
      enable = true;
      domain = "whoami.${labDomain}";
      serviceName = "whoami";
      servicePort = 80;
    };
  };
}

When gateway.enable = true, Catallaxy automatically generates an HTTPRoute (or TLSRoute for passthrough mode) pointing to your service. The route is added to the same bundle as your resources.

Gateway options

OptionDefaultDescription
gateway.enablefalseGenerate a Gateway API route
gateway.mode"terminate""terminate" for HTTPRoute, "passthrough" for TLSRoute
gateway.domain""Hostname for the route
gateway.serviceNameapp nameBackend service name
gateway.servicePort80Backend service port
gateway.gatewayRef"default-gateway"Name of the Gateway resource to attach to
gateway.gatewayNamespace"kube-system"Namespace of the Gateway resource

Custom app options reference

OptionDefaultDescription
enabletrueWhether to deploy this app
phase"apps"Deployment phase
namespaceapp nameKubernetes namespace
createNamespacetrueAuto-create the namespace
helmCharts{}Helm charts (same shape as phase bundle helmCharts)
resources{}Typed Kubernetes resource definitions
yamls[]Raw YAML manifests (strings or paths)

When to use custom apps vs. a full component

Use components.custom.apps when:

  • You need to deploy an application that is specific to your lab.
  • The app does not need cross-component ref wiring.
  • You want a quick deployment without writing a module.

Write a full component module (see Adding Components) when:

  • Other components need to reference this component via ref attributes.
  • The component has complex configuration options that benefit from the NixOS module type system.
  • You intend to contribute the component upstream.