Introduction
Catallaxy is a declarative Kubernetes platform built on the NixOS module system. It lets you define multi-cluster environments entirely in Nix, producing rendered manifests and runtime tooling as build outputs — no imperative orchestration required.
The name
The term “catallaxy” comes from F.A. Hayek’s description of a spontaneous order: a complex, coordinated system that emerges not from central planning, but from independent actors following their own rules. In economics, this is the market. In catallaxy, it is your infrastructure.
Each component — cert-manager, ArgoCD, Prometheus, Kanidm, and many others — is a self-contained declaration. It defines its own options, its own defaults, and writes its own manifests into the appropriate deployment phase. No component knows the full picture. Yet through Nix’s lazy evaluation and the module system’s merge semantics, these independent declarations compose into a coherent, cross-referenced, multi-cluster platform.
There is no imperative glue. No ordering logic scattered across scripts. Components declare what they need, reference what they depend on, and the system resolves it all at build time.
What it does
You write Nix modules that describe your lab — its clusters, their components, networking, identity, observability, and anything else you need. Catallaxy evaluates those modules and produces:
- Rendered Kubernetes manifests — Helm charts templated, typed resources serialized, raw YAML collected, all organized by deployment phase.
- A deployment package — manifests bundled with metadata, ready for application via kapp, ArgoCD, or Fleet.
- Runtime tooling — a CLI (
cata) that handles cluster lifecycle, secret management, PKI, DNS, and operational commands defined in your lab configuration.
The system has two layers:
- Nix modules define the configuration DSL, perform type checking, resolve cross-references between clusters, and render all manifests at build time.
- A Rust CLI (
cata) orchestrates runtime operations: evaluating Nix expressions, applying manifests to clusters, managing secrets, and running ops commands.
Status
Catallaxy is functional and in active use, but the API is not yet stable. Expect breaking changes between minor versions. Feedback and contributions are welcome.
Where to go from here
- Getting Started — install prerequisites and stand up your first lab.
- The architecture and component reference sections cover the internals in detail.
Why Catallaxy
Kubernetes platform engineering has an accidental complexity problem: YAML sprawl across environments, deployment ordering that lives in tribal knowledge, brittle bash glue that breaks silently, and a bootstrap chicken-and-egg that someone has to solve by hand every time.
Catallaxy treats your platform like a compilation problem. Declare components in typed Nix modules. Cross-cluster references resolve through lazy evaluation at build time. Phase ordering is a dependency graph, not a runbook. The same declarations compile to kapp, ArgoCD, or Fleet output without changing component code.
The problems we keep solving by hand
YAML sprawl
Every Kubernetes environment accumulates YAML. Helm values files for dev, staging, prod. Kustomize overlays stacked on top of overlays. Patches for patches. Across a multi-cluster platform, you end up with thousands of lines of templated configuration, most of it duplicated with minor variations. When something needs to change, you grep across directories and hope you found every copy.
Tribal knowledge
How do you deploy this platform from scratch? Which namespace needs to exist before the operator can start? What order do the Helm releases go in? Where does the CA certificate come from, and which components need it injected? The answers live in someone’s head, a runbook that’s three versions behind, or a Slack thread from last year. Every new team member re-discovers this the hard way.
Brittle procedural scripting
The gap between “here are my Helm charts” and “here is a running platform” gets filled with scripts. Bash that shells out to kubectl, helm, and jq in careful sequence. Python wrappers that parse YAML to generate more YAML. CI pipelines stitched together with retry loops, sleep statements, and post-deploy health checks that paper over ordering bugs. These scripts work until they don’t — and when they break, they break silently or in ways that are hard to diagnose.
The bootstrap problem
Your child clusters get GitOps, declarative config, drift detection, and automated reconciliation. But the management cluster that runs all of that? It was click-ops’d into existence on AWS. Someone followed a wiki page, clicked through a console, ran some Terraform, and manually applied a handful of Helm charts until ArgoCD was alive enough to take over.
The management plane is always manual. Always imperative. Always a special case that doesn’t get the same rigor as everything it manages. And when you need to rebuild it — disaster recovery, region migration, new environment — you discover how much institutional knowledge was baked into that original bootstrap sequence that nobody wrote down completely.
No type safety
Helm values are untyped YAML. A misspelled key is silently ignored. A wrong type produces valid YAML that fails at apply time — or worse, applies successfully and breaks at runtime. You find out when the on-call gets paged, not when the configuration was written. There is no compile step, no editor completion, no structural guarantee that what you wrote matches what the chart expects.
Non-reproducible builds
The same Helm chart, the same values file, can produce different output depending on the Helm binary version, which OCI registry responded, whether a transitive dependency was cached, or what the network looked like at build time. “It worked yesterday” is not an explanation, but it’s often all you have. Diffing what actually changed between two deploys requires forensic effort.
How Catallaxy addresses this
Catallaxy replaces ad-hoc tooling with a compiler-like approach: declare what you want, and the system resolves it into exactly the manifests each cluster needs.
Nix as the foundation
The NixOS module system provides typed options with defaults, lazy evaluation for cross-references, and deterministic builds. Your entire platform — every component, every cluster, every environment variation — is a single Nix expression that evaluates to a set of Kubernetes manifests. Cross-cluster references (like pointing one cluster’s OTEL collector at another cluster’s Tempo endpoint) resolve at build time through lazy evaluation. No runtime service discovery. No ordering scripts. No glue.
Single-file components
Each infrastructure component is a self-contained Nix module. It declares its own options, its own defaults, and writes its own manifests into the appropriate deployment phase. Want to understand what the cert-manager component does? Read one file. Want to add a new component? Write one file. There is no configuration scattered across multiple directories, no implicit dependencies between files, and no hidden wiring.
Phase-based ordering
CRDs before operators. Operators before infrastructure. Infrastructure before apps. This ordering is declared as a dependency graph that the build system resolves, not as a sequence of steps in a script. The bootstrap problem — which resources must exist before others can be created — becomes a build-time property. Phases that have no content are automatically dropped. The CLI deploys phases in order, waiting for CRDs to be established before deploying resources that depend on them.
Type-checked configuration
Kubernetes resources are typed from OpenAPI specs and CRD schemas. Helm values are structured Nix attrsets, not free-form YAML. Structural errors surface at nix eval time, before anything is rendered or applied. Your editor can provide completion. Your CI can catch misconfigurations. You find problems when you write the code, not when you deploy it.
Reproducible by construction
Manifests are Nix store derivations — content-addressed, cacheable, and deterministic. Same inputs always produce the same outputs, regardless of when or where you build them. You can diff the rendered manifests between any two configurations and see exactly what changed, down to the individual YAML resource. No forensic effort required.
Multiple deployment targets
The same component declarations compile to output for kapp (direct apply), ArgoCD, or Fleet. Switching deployment strategy is a single option change — no component code needs to be rewritten. The rendering pipeline transforms the same intermediate representation into strategy-specific directory layouts and metadata.
Who this is for
Catallaxy is for platform engineers and DevOps practitioners who:
- Have felt the pain of managing multi-cluster Kubernetes environments with ad-hoc tooling
- Are comfortable with (or willing to learn) Nix as an infrastructure tool
- Want their platform defined in code that is typed, reproducible, and reviewable
- Are tired of tribal knowledge and want a single source of truth that compiles
If you recognize that Nix’s guarantees — purity, reproducibility, lazy evaluation, composability — are exactly what infrastructure configuration needs, this project is for you.
Getting started
See Prerequisites to set up your environment, then walk through the Quick Start to stand up a working multi-cluster lab.
Prerequisites
Catallaxy requires two things on your system. Everything else is provided by the flake.
Nix with flakes enabled
Install Nix using the Determinate Systems installer, which enables flakes by default:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -o install-self
If you already have Nix installed, ensure flakes are enabled. Add the following to ~/.config/nix/nix.conf if it is not already present:
experimental-features = nix-command flakes
Docker
A running Docker daemon is required for local development. Catallaxy uses k3d to run K3s clusters inside Docker containers.
Install Docker through your system’s package manager or from docker.com. Verify it is running:
docker info
That is everything
You do not need to install kubectl, Helm, kapp, k3d, talosctl, or any other Kubernetes tooling. The catallaxy flake provides all of these through its dev shell. When you run nix develop, every tool the CLI needs is available on your PATH.
This is intentional. Pinning tool versions in the flake eliminates “works on my machine” issues and ensures the CLI, the manifest renderer, and the cluster tooling all agree on versions.
Quick Start
This guide walks you through standing up the example homelab — a multi-cluster local environment with networking, identity, GitOps, observability, and more — all running in Docker via k3d.
Clone the repository
git clone https://github.com/onepunchtech/catallaxy.git
cd catallaxy
Enter the dev shell
nix develop
This drops you into a shell with every tool catallaxy needs: cata, kubectl, helm, kapp, k3d, and others. You do not need any of these installed on your system.
Bring the lab up
cata --flake ./examples/labs#homelab.local lab up
This is the main command. It evaluates the lab configuration defined in examples/labs/flake.nix for the lab named homelab, provisions k3d clusters, and applies all rendered manifests in phase order. Phases run from CRDs and namespaces through networking, operators, infrastructure, GitOps, databases, and applications.
The --flake ./examples/labs#homelab argument points to the flake directory and selects the homelab lab by name. This pattern is used for all cata commands.
Set up DNS
cata --flake ./examples/labs#homelab.local lab dns --setup
Configures your local DNS resolution so that *.homelab.test domains route to the lab’s ingress. This lets you access services by name in your browser without editing /etc/hosts.
Trust the lab CA
cata --flake ./examples/labs#homelab.local lab trust --setup
Adds the lab’s certificate authority to your system’s trust store. The lab generates its own CA via cert-manager, and this command ensures your browser and CLI tools trust the TLS certificates it issues. Without this, you will see certificate warnings on every service.
Verify the lab is running
cata --flake ./examples/labs#homelab.local lab status
Shows the state of each cluster and its components. Once everything is healthy, the lab’s services are accessible at their configured domains:
- ArgoCD — https://argocd.homelab.test
- Grafana — https://grafana.homelab.test
Additional services depend on which components are enabled in the lab configuration.
Tear it down
cata --flake ./examples/labs#homelab.local lab down # stop clusters (preserves state)
cata --flake ./examples/labs#homelab.local lab destroy # delete everything
lab down stops clusters but preserves state — run lab up to restart. lab destroy deletes clusters, services, and network completely.
Next steps
The example lab is a useful reference, but the real power is defining your own. See Creating Your Own Lab to set up a standalone flake that imports catallaxy as an input.
Creating Your Own Lab
The example lab is bundled with catallaxy for reference, but real usage starts with your own flake. You define your lab topology in Nix modules and catallaxy evaluates them into rendered manifests and runtime tooling.
Quick start
nix flake init -t github:onepunchtech/catallaxy#consumer
This creates a working consumer flake with a custom component example.
Minimal flake
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
catallaxy.url = "github:onepunchtech/catallaxy";
};
outputs = { nixpkgs, flake-utils, catallaxy, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
mkLab = catallaxy.${system}.mkLab;
in {
labs."my-platform" = (mkLab {
modules = [ ./lab.nix ];
}).config.lab.out.cliConfig;
}
);
}
mkLab takes a list of NixOS-style modules and evaluates them through catallaxy’s module system — the same one that powers the example labs.
Define your lab topology
Create lab.nix alongside the flake:
{ config, lib, ... }:
{
lab.name = "my-platform";
lab.dns.zone = "mylab.test";
lab.clusters.app = { ... }: {
cluster.name = "app";
cluster.kubernetes = {
distribution = "k3s";
controlPlanes = 1;
workers = 0;
};
components.cert-manager.enable = true;
components.gateway.enable = true;
};
}
Each component is a self-contained module. Enabling it causes it to write its Helm charts, resources, and configuration into the appropriate deployment phase. The phase system handles ordering and dependencies.
Custom components
Add your own components as modules:
mkLab {
modules = [
./lab.nix
./components/my-app.nix # Custom component
];
}
See Writing Components for the full guide.
Splitting configuration across files
As your lab grows, split it into aspects (features), clusters, and environment overlays:
mkLab {
modules = [
./topology.nix # Cluster definitions
./networking.nix # Gateway, DNS, cert-manager
./identity.nix # Kanidm users, groups, OAuth2
./observability.nix # Prometheus, Loki, Grafana
./env/local.nix # Environment-specific overrides
];
};
This is the pattern the example lab uses: aspects define features, clusters compose aspects, and environments provide thin overrides for local, staging, or production targets.
Cross-cluster references
Components can reference values from other clusters through the lab argument:
{ config, lab, ... }:
{
components.otel-collector = {
enable = true;
exporters.otlp.endpoint = lab.clusters.obs.components.tempo.ref.otlpGrpc;
};
}
Every component exposes a ref attribute set with computed, read-only values — endpoints, namespaces, service names. Refs are always available, even when the component is disabled.
Running your lab
nix develop github:onepunchtech/catallaxy
cata --flake '.#my-platform' lab up
cata --flake '.#my-platform' lab down # Stop (preserves state)
cata --flake '.#my-platform' lab destroy # Delete everything
Building manifests without applying
nix build '.#labPackages.x86_64-linux."my-platform"'
This produces the full deployment package — manifests, metadata, images list, and ops tooling — as a store path you can inspect, diff, or ship to CI.
Architecture Overview
Catallaxy is a declarative Kubernetes platform built on two foundations: the NixOS module system for configuration and manifest rendering, and a Rust CLI for runtime orchestration. This separation keeps the build-time logic pure and reproducible while giving operators a single command-line tool for day-to-day cluster management.
Two-Layer System
flowchart TD
A["User Configuration<br/>(Nix modules / flake)"]
B["<b>Nix Layer</b> (build-time)<br/>Module evaluation<br/>Type checking & defaults<br/>Helm template rendering<br/>Typed K8s resource generation<br/>Strategy-specific output<br/>(kapp / argocd / fleet)"]
C["<b>Rust CLI</b> (runtime)<br/>Cluster provisioning (k3d)<br/>Manifest application (kapp)<br/>Secret injection (SOPS)<br/>PKI management<br/>Backup/restore (Velero)<br/>CAPI bootstrap & pivot"]
D["Kubernetes Clusters"]
A -->|"nix eval / nix build"| B
B -->|"JSON config + store paths"| C
C -->|"kubectl / kapp"| D
Nix layer – Everything that can be computed at build time lives here. The NixOS module system evaluates lab and cluster configurations, resolves cross-references between components and clusters, renders Helm charts via helm template, generates typed Kubernetes resources, and packages everything into Nix store derivations. The output is deterministic: the same configuration always produces the same manifests.
Rust CLI – The cata binary handles operations that require interacting with the outside world: provisioning clusters, applying manifests, managing secrets, issuing PKI certificates, and orchestrating CAPI bootstrap sequences. It calls nix eval and nix build to obtain configuration data and rendered manifests, then uses external tools (kubectl, kapp, k3d, sops, velero) to act on them.
Multipass Compiler Analogy
The system can be understood as a multi-pass compiler where Kubernetes manifests are the compiled output:
| Pass | What it does | Where it lives |
|---|---|---|
| Declaration | High-level NixOS options define the user interface. Components declare options like enable, namespace, phase, and domain-specific settings. | modules/lab/cluster/components/ |
| Intermediate Representations | The module system computes intermediate representations: phase bundles (Helm charts + typed resources + raw YAML), provisioning config, cluster topology, and software bill of materials. | modules/lab/cluster/out.nix, modules/lab/out.nix |
| Target Rendering | Strategy-specific renderers transform the IR into deployment-ready output for kapp, ArgoCD, or Fleet. Each renderer produces a different directory layout. | lib/renderers/kapp.nix, lib/renderers/argocd.nix, lib/renderers/fleet.nix |
This multi-pass design means the same component declarations can target different CD systems without changing any component code.
Separation of Eval, Build, and Runtime
The three phases have distinct responsibilities and never cross boundaries:
Eval Phase (nix eval)
The CLI calls nix eval --json to obtain cluster and lab configuration as JSON. This evaluates the module system but does not build any derivations. The result contains:
- Cluster metadata (name, provider, network config)
- Component settings (enabled state, versions, namespaces)
- Provisioner configuration (k3d cluster names, images, ports)
- Lab topology (cluster names, services, DNS info)
Build Phase (nix build)
When manifests are needed, the CLI calls nix build on the lab package or cluster manifests output. This triggers Helm chart rendering, resource serialization, and strategy-specific packaging – all inside the Nix sandbox. The output is a Nix store path containing:
- Numbered phase directories (
00-crds/,01-namespaces/, etc.) - Rendered YAML manifests within each phase
- A
.phase-orderfile encoding deployment sequence - A
.deploy-configfile with strategy-specific settings - A
metadata.jsonfile with topology and SBOM data
Runtime Phase (cata CLI)
The CLI reads the built store paths and orchestrates deployment:
- Provision clusters via k3d (or CAPI bootstrap for production)
- Discover phases from the rendered manifest directory
- Deploy phases sequentially via kapp, injecting SOPS secrets at the appropriate phase boundaries
- Wait for CRDs to be established before deploying phases that depend on them
This separation means Nix never needs network access during builds (no import-from-derivation), and the CLI never needs to understand Helm charts or Nix module evaluation.
Lab, Cluster, and Component Hierarchy
Catallaxy organizes infrastructure in a four-level hierarchy: Lab > Cluster > Component > Phase/Bundle. Each level adds structure and enables cross-references that the NixOS module system resolves through lazy evaluation.
Labs
A lab is a multi-cluster environment. It defines which clusters exist, how they relate to each other, what infrastructure services run alongside them (DNS, registry, ingress proxy), and what deployment strategy to use.
# examples/labs/labs/default.nix
{ config, lib, ... }:
{
lab.name = "homelab.local";
lab.cd.strategy = "kapp";
lab.clusters.core = { imports = [ ../clusters/core.nix ]; };
lab.clusters.obs = { imports = [ ../clusters/obs.nix ]; };
lab.clusters.mgmt = { imports = [ ../clusters/mgmt.nix ]; };
}
Labs provide:
- Cluster composition – Which clusters exist and what modules they import
- Shared infrastructure – DNS servers, container registries, TLS ingress proxies (all managed as Docker containers alongside the clusters)
- Deployment strategy – Whether to render output for kapp (direct apply), ArgoCD, or Fleet
- Ops commands – Component-aware shell scripts for operational tasks like resetting passwords or triggering backups
- Environment layering – A lab is composed from aspects (feature modules) and environment deltas (provisioner, DNS, TLS settings) via
mkLab
Example Lab Structure
examples/labs/
flake.nix # Composes: mkLab [ labs/default.nix envs/local.nix ]
aspects/ # Pure feature modules (no env awareness)
networking.nix
identity.nix
gitops.nix
clusters/ # Aspect composition
core.nix # = networking + identity + gitops + ...
obs.nix # = networking + monitoring
labs/
default.nix # Lab topology + shared ops
envs/ # Thin environment deltas
local.nix # k3d provisioner, local DNS
prod.nix # DO provisioner, ACME TLS
This layering means the same cluster definitions can target local k3d development or production cloud clusters by swapping only the environment file.
Clusters
A cluster is a single Kubernetes cluster with its own set of enabled components, phase ordering, and provisioner configuration. Clusters are defined as NixOS module evaluations within a lab.
# examples/labs/clusters/core.nix
{ config, lib, lab, ... }:
{
imports = [
../aspects/networking.nix
../aspects/identity.nix
../aspects/gitops.nix
];
cluster.name = "core";
cluster.kubernetes.version = "1.31";
cluster.kubernetes.workers = 0;
}
Each cluster configuration produces:
cluster.out.phases– Merged phase bundles with rendered manifest derivationscluster.out.phaseOrder– Sorted list of phase names for deployment sequencingcluster.out.topology– Computed topology map (name, provider, nodes, network, enabled components)cluster.out.sbom– Software bill of materials (component versions)
Components
A component is a self-contained infrastructure unit defined in a single Nix file. Components declare their own options and write Helm charts, typed Kubernetes resources, or raw YAML into phase bundles when enabled.
The Single-File Component Pattern
Every component follows this structure:
# modules/lab/cluster/components/<category>/<name>.nix
{ config, lib, cataCharts, k8sSpecs, ... }:
let
cfg = config.components.<name>;
in
{
# 1. Option declarations
options.components.<name> = {
enable = lib.mkEnableOption "<Name>";
phase = lib.mkOption {
type = lib.types.str;
default = "<phase>";
description = "Deployment phase";
};
namespace = lib.mkOption {
type = lib.types.str;
default = "<name>";
};
chart = lib.mkOption {
type = lib.types.package;
default = cataCharts.<name>.chart;
};
ref = lib.mkOption {
type = lib.types.attrs;
readOnly = true;
description = "Computed references for cross-component wiring";
};
# ... domain-specific options
};
# 2. Configuration (always evaluated, even when disabled)
config = lib.mkMerge [
# Computed refs -- always available so other components can reference them
{
components.<name>.ref = {
namespace = cfg.namespace;
serviceName = "<name>";
port = 8080;
url = "http://${cfg.ref.serviceName}.${cfg.ref.namespace}.svc:${toString cfg.ref.port}";
};
}
# Phase writer -- only active when enabled
(lib.mkIf cfg.enable {
phases.${cfg.phase}.bundles.<name> = {
createNamespaces = [ cfg.namespace ];
helmCharts.<name> = {
chart = cfg.chart;
namespace = cfg.namespace;
releaseName = "<name>";
values = {
# Helm values here
};
};
};
})
];
}
The ref Pattern
The ref attribute is the key mechanism for cross-component wiring. It is:
- readOnly – Set by the component itself, not overridable by users
- Always computed – Available even when the component is disabled, so other components can safely reference it without guards
- Lazy – Nix’s lazy evaluation means the ref values are only computed when accessed
This enables patterns like:
# In the OTEL collector component
config.components.otel-collector.exporters.otlp.endpoint =
config.components.tempo.ref.otlpGrpcEndpoint;
The OTEL collector can reference Tempo’s endpoint regardless of evaluation order. If Tempo is disabled, the ref still exists (with its default values), though the OTEL collector’s configuration would need to handle that case.
Cross-Cluster References via lab
Components receive a lab argument that provides access to all clusters in the lab. This enables cross-cluster wiring through Nix’s lazy evaluation:
# In core cluster's OTEL collector
{ config, lib, lab, ... }:
{
components.otel-collector.exporters.otlp.endpoint =
lab.clusters.obs.components.tempo.ref.otlpGrpc;
}
This works because:
- The lab evaluates all clusters as NixOS modules with a shared
labargument - Nix’s lazy evaluation means cluster A can reference cluster B’s computed values without creating circular dependencies (as long as the dependency graph is acyclic at the value level)
- The
refpattern ensures the target values exist even if the referenced component is disabled
Practical Example: Observability Pipeline
flowchart LR
subgraph core["core cluster"]
A["otel-collector<br/>(agent mode)"]
end
subgraph obs["obs cluster"]
B["otel-gateway<br/>(gateway mode)"]
C["loki / tempo"]
end
A -->|"OTLP/gRPC"| B
B --> C
The core cluster’s OTEL collector is configured to export to the obs cluster’s gateway endpoint. This endpoint URL is computed from the obs cluster’s component refs and resolved at Nix evaluation time – no runtime service discovery needed.
Registering New Components
When adding a new component:
- Create the component file at
modules/lab/cluster/components/<category>/<name>.nix - Add the import to
modules/lab/cluster/components/<category>/default.nix - If creating a new category, add it to
modules/lab/cluster/components/default.nix
When adding a new Helm chart for a component:
- Add the chart definition to
lib/charts.nixwith repository URL, version, and content hash
Manifest Rendering Pipeline
The manifest pipeline transforms high-level component declarations into deployment-ready Kubernetes YAML. It runs entirely at Nix build time, producing deterministic output in the Nix store.
Pipeline Stages
flowchart TD
A["<b>1. Bundle Accumulation</b><br/>(per-phase)"]
B["<b>2. Phase Merging</b><br/>(cluster.out.phases)"]
C["<b>3. Strategy Rendering</b><br/>(kapp / argocd / fleet)"]
D["<b>4. Lab Packaging</b><br/>(lab.out.package)"]
E["Nix store path"]
A -->|"helmCharts, resources, yamls,<br/>createNamespaces into bundles"| B
B -->|"merge bundles per phase<br/>into single derivations"| C
C -->|"strategy-specific renderer"| D
D -.->|"all clusters' manifests +<br/>metadata.json"| E
Stage 1: Bundle Accumulation
Components write their Kubernetes resources into bundles within their assigned phase. A bundle is the finest-grained deployment unit and can contain three types of content:
phases.${cfg.phase}.bundles.cert-manager = {
# Namespaces to create (collected across all phases, created in the namespaces phase)
createNamespaces = [ cfg.namespace ];
# Helm charts to render via helm template
helmCharts.cert-manager = {
chart = cfg.chart;
namespace = cfg.namespace;
releaseName = "cert-manager";
values = {
crds.enabled = true;
replicaCount = 1;
};
extraOpts = [ "--include-crds" ];
kustomize = {
enable = false;
patches = [];
resources = [];
};
};
# Typed Kubernetes resources (checked by the NixOS module type system)
resources.lab-ca-issuer = {
apiVersion = "cert-manager.io/v1";
kind = "ClusterIssuer";
metadata.name = "lab-ca";
spec.ca.secretName = "lab-ca-ca-secret";
};
# Raw YAML (strings, paths, or derivations)
yamls = [ ];
};
Helm Charts
Helm charts are rendered using helm template inside a Nix derivation (lib/render.nix:renderHelmChart). The rendering process:
- Writes
values.yamlfrom the Nix attrset - Runs
helm templatewith the specified release name, namespace, and extra options - Post-processes the output to inject
metadata.namespaceinto namespaced resources (sincehelm templatedoes not apply namespace likehelm installdoes) - Optionally applies kustomize patches if
kustomize.enable = true
Typed Resources
Resources defined in resources are Nix attribute sets that conform to Kubernetes API types generated from OpenAPI specs and CRDs. The type system catches structural errors at nix eval time.
Raw YAML
The yamls list accepts strings (inline YAML), paths, or derivations. CRD YAML files are automatically split by API group for manageability.
Stage 2: Phase Merging
The cluster.out.phases option (modules/lab/cluster/out.nix) merges all bundles within each phase:
- Collect all namespaces from all bundles across all phases
- Merge bundle contents per phase: fold all
helmCharts,resources, andyamlsfrom all bundles in that phase - Inject namespace YAMLs into the
namespacesphase - Render derivations via
render.renderPhase, which produces a store path containing all YAML files for that phase - Filter empty phases – phases with no content are dropped
The result is an attrset where each key is a phase name and each value contains:
{
order = 10; # Numeric ordering
dependsOn = [ ... ]; # Phase dependencies
keepResources = false;
pruneStrategy = "default";
waitForReady = true;
timeout = "10m";
waitForCRDs = false;
crdNames = [];
package = <derivation>; # Rendered YAML files
}
Stage 3: Strategy Rendering
The lab.out.manifests option (modules/lab/out.nix) passes each cluster’s merged phases through a strategy-specific renderer from lib/renderers/. The lab’s cd.strategy setting selects the renderer.
kapp Renderer
Produces a flat directory structure with numbered phase directories:
kapp-core/
core/
00-crds/
cilium-crds.yaml
01-namespaces/
namespaces-resources.yaml
02-networking/
cilium.yaml
traefik.yaml
03-operators/
cert-manager.yaml
...
.phase-order # Ordered list of phase names
.deploy-strategy # "kapp"
.deploy-config # waitTimeout: 10m
The kapp renderer also applies resource name prefixing (when lab.prefix is set) and generates .crd-wait files for phases that require CRDs to be established before deployment.
ArgoCD Renderer
Produces Application and ApplicationSet resources that point to a git repository. The rendered manifests are organized for ArgoCD to discover and sync.
Fleet Renderer
Produces Bundle resources for Rancher Fleet, with similar directory organization but Fleet-specific metadata.
Stage 4: Lab Packaging
The lab.out.package option combines all clusters’ rendered manifests into a single Nix derivation:
lab-homelab.local/
metadata.json # Pretty-printed lab metadata
manifests/
core -> /nix/store/...-kapp-core/core
obs -> /nix/store/...-kapp-obs/obs
mgmt -> /nix/store/...-kapp-mgmt/mgmt
bin/
homelab.local-ops # Lab ops tool (if defined)
The metadata.json file contains:
- Lab name and prefix
- List of cluster names
- CD strategy and config
- Per-cluster topology (provider, nodes, network, enabled components)
- Per-cluster software bill of materials (component versions)
- Per-cluster namespace lists (used by lint checks)
How the CLI Consumes the Pipeline Output
When the user runs cata lab up, the CLI:
- Calls
nix evalto get the lab’s CLI config (cluster names, services, DNS, etc.) - Provisions infrastructure services (DNS, registry, ingress) as Docker containers
- Provisions each cluster via k3d
- Calls
nix buildon the lab package, triggering the full rendering pipeline - For each cluster, discovers phases from the
.phase-orderfile - Deploys phases sequentially via kapp, waiting for CRDs and injecting SOPS secrets at phase boundaries
The cata lab publish command follows the same build step but instead pushes the rendered manifests to a git repository for GitOps consumption.
Built-in Phase Ordering
Phases are deployed in numeric order. The built-in phases and their default ordering:
| Order | Phase | Purpose |
|---|---|---|
| -10 | crds | Custom Resource Definitions |
| -5 | namespaces | Namespace creation (auto-collected from all bundles) |
| 0 | networking | CNI, gateway, service mesh |
| 10 | operators | Operator deployments (cert-manager, CNPG, etc.) |
| 20 | secrets | Secret injection and external secret sync |
| 30 | infrastructure | Infrastructure services (DNS, storage, registries) |
| 40 | gitops | GitOps controllers (ArgoCD) |
| 50 | databases | Database instances |
| 90 | apps | Application workloads |
| 100 | workloads | User workloads |
Components select their phase via the phase option. Phases that end up empty (no bundles with content) are automatically excluded from the rendered output.
The NixOS Module System
Catallaxy uses the NixOS module system as its configuration engine. This is the same system that powers NixOS (the Linux distribution), but applied to Kubernetes cluster configuration instead of operating system configuration. This page explains why it was chosen and how Catallaxy uses its key features.
Why NixOS Modules
The NixOS module system provides several properties that are difficult to achieve with other configuration tools:
Type Checking at Evaluation Time
Every option has a declared type. When a user sets a value that does not match the expected type, the error is caught during nix eval – before any manifest is rendered or any cluster is touched.
# This declaration...
options.components.cert-manager.namespace = lib.mkOption {
type = lib.types.str;
default = "cert-manager";
};
# ...means this is caught immediately:
components.cert-manager.namespace = 42;
# error: A definition for option `components.cert-manager.namespace`
# is not of type `string`.
The type system extends to complex structures. Kubernetes resources are typed using NixOS module types generated from OpenAPI specs and CRDs, so structural errors in resource definitions are caught at evaluation time rather than at apply time.
Lazy Evaluation and Cross-References
Nix is a lazy language: values are only computed when they are needed. This enables circular module references that would cause infinite loops in eager languages.
# Module A sets a value that references module B
config.components.otel-collector.endpoint =
config.components.tempo.ref.otlpGrpc;
# Module B sets a value that references module A
config.components.tempo.forwarders =
[ config.components.otel-collector.ref.receiverEndpoint ];
As long as the dependency graph is acyclic at the value level (no value depends on itself), Nix resolves everything correctly. This is what makes the ref pattern and cross-cluster references possible.
Merge Semantics
When multiple modules set the same option, the module system merges them according to the option’s type:
- Attribute sets are recursively merged
- Lists are concatenated
- Scalars cause an error (unless one uses
mkDefault,mkForce, or priority)
This is how components from different files accumulate bundles into the same phase without coordination:
# cert-manager writes to phases.operators.bundles
phases.operators.bundles.cert-manager.helmCharts.cert-manager = { ... };
# prometheus also writes to phases.operators.bundles
phases.operators.bundles.prometheus.helmCharts.prometheus = { ... };
The module system merges these two definitions into a single phases.operators.bundles attrset.
Defaults and Overrides
Options can have defaults (mkDefault), and users can override them at multiple priority levels:
# Component sets a default phase
phase = lib.mkDefault "operators";
# User overrides it in their cluster config
components.cert-manager.phase = "infrastructure";
This enables the environment layering pattern: aspects define feature defaults, and environment deltas override provisioner settings, DNS configuration, and TLS mode.
Assertions
Modules can declare assertions that are checked after evaluation:
config.assertions = [
{
assertion = config.components.cert-manager.acme.enable
-> config.components.cert-manager.acme.email != "";
message = "ACME email must be set when ACME is enabled";
}
];
Failed assertions are collected and reported as a single error, giving the user a complete list of problems to fix.
The out Pattern
Computed output values follow a convention of being placed under an out attribute. These are readOnly options that the module system computes from other configuration values.
Cluster-Level out
cluster.out (modules/lab/cluster/out.nix) computes:
topology– Name, provider, node counts, network config, and which components are enabledsbom– Software bill of materials (component versions)phases– Merged phase bundles rendered as Nix store derivationsphaseOrder– Sorted list of phase names
# cluster.out.phases is computed by merging all bundles per phase
# and rendering them through lib/render.nix
config.cluster.out.phases = let
mergePhase = phaseName: phaseCfg:
let
bundleValues = lib.attrValues phaseCfg.bundles;
allHelmCharts = lib.foldl' (acc: b: acc // b.helmCharts) {} bundleValues;
allResources = lib.foldl' (acc: b: acc // b.resources) {} bundleValues;
allYamls = lib.concatMap (b: b.yamls) bundleValues;
in
render.renderPhase phaseName {
helmCharts = allHelmCharts;
resources = allResources;
yamls = allYamls;
};
in
lib.mapAttrs mergePhase config.phases;
Lab-Level out
lab.out (modules/lab/out.nix) computes:
cliConfig– JSON-serializable config that the Rust CLI needs (cluster names, services, DNS, registry, ops tool path)allClusters– All evaluated cluster configs (used for cross-cluster references)manifests– Per-cluster rendered manifest packages, passed through the strategy rendererpackage– Single derivation combining all clusters’ manifests with metadata
Component-Level ref
Components use ref for their computed outputs. Unlike out, refs are always set (even when the component is disabled) so that other components can reference them safely:
config = lib.mkMerge [
# Always set, regardless of enable state
{
components.tempo.ref = {
namespace = cfg.namespace;
otlpGrpc = "tempo-distributor.${cfg.namespace}.svc:4317";
otlpHttp = "tempo-distributor.${cfg.namespace}.svc:4318";
};
}
# Only writes to phases when enabled
(lib.mkIf cfg.enable {
phases.${cfg.phase}.bundles.tempo = { ... };
})
];
Avoiding Import From Derivation (IFD)
Import From Derivation (IFD) occurs when Nix needs to build a derivation during evaluation in order to import its output. IFD breaks parallelism, defeats caching, and makes evaluation unpredictable.
Catallaxy avoids IFD by keeping all configuration data as Nix expressions:
- Helm chart references are Nix store paths (fetched at flake lock time, not at eval time)
- Kubernetes API types are pre-generated Nix files committed to the repository
- Component configurations are pure Nix attrsets, not derived from external data
The only place derivations appear during evaluation is in out options that produce store paths for rendered manifests. These are types.raw or types.package options that Nix builds lazily – they are not imported back into the evaluation.
Module Evaluation Entry Points
The Rust CLI interacts with the Nix module system through two flake outputs:
clusters.<system>.<name> (eval)
Returns a JSON-serializable representation of a cluster’s configuration. The lib/eval.nix:clusterConfigToJSON function strips the evaluated config down to the fields the CLI needs.
labPackages.<system>."<name>" (build)
Triggers a full build of the lab package, producing rendered manifests for all clusters. This is the primary entry point for cata lab up and cata lab apply.
The CLI uses nix eval --json for the first and nix build --no-link --print-out-paths for the second, keeping a clean separation between configuration inspection and manifest production.
Nix-Specific Conventions
A few conventions specific to how Catallaxy uses the module system:
- Do not use
mkIfinsideresourcesoryamlsvalues. Uselib.optionalAttrsorif/then/elseinstead.mkIfproduces a NixOS module merge operation, which does not work inside attribute values that are passed directly to derivation builders. - Charts come from
cataCharts.<name>, defined inlib/charts.nix. Components accept achartoption so users can override the chart derivation. - Lab names support dots (e.g.,
homelab.local). The CLI quotes them in nix eval:labs.{system}."homelab.local". - All
refattributes arereadOnly, preventing users from accidentally overriding computed wiring values.
The Rust CLI
The cata binary is a Rust CLI built with clap and tokio. It handles all runtime operations: provisioning clusters, applying manifests, managing secrets and PKI, orchestrating backups, and bootstrapping CAPI management clusters.
The CLI does not contain any Kubernetes manifest logic. It delegates configuration evaluation and manifest rendering to Nix, then uses external tools (kubectl, kapp, k3d, sops, velero, clusterctl, ykman) to act on the results.
Global Options
cata [OPTIONS] <COMMAND>
Options:
--flake <FLAKE> Flake reference (path, URL, or ref#name) [env: CATALLAXY_FLAKE] [default: .]
-v, --verbose Verbose output
The --flake flag specifies the Nix flake containing the lab/cluster configuration. The fragment after # (e.g., ./examples/labs#homelab.local) is used as the default lab or cluster name for subcommands.
How the CLI Interacts with Nix
The CLI communicates with the Nix layer through two mechanisms:
nix eval --json – Used to read configuration without building anything. Returns cluster config, lab config, or cluster/lab name lists as JSON.
nix build --no-link --print-out-paths – Used to build rendered manifests. Returns the Nix store path containing the built output.
The CLI resolves flake references (path + optional fragment) and constructs the correct attribute path for each operation. For example, cata --flake ./examples/labs#homelab.local lab up evaluates labs.x86_64-linux."homelab.local" and builds labPackages.x86_64-linux."homelab.local".
Runtime Dependencies
The CLI shells out to external tools that must be available in PATH. When built via nix build .#cata, all runtime tools are wrapped into the binary’s path. Inside nix develop, they are provided by the dev shell.
Required tools: nix, docker, kubectl, kapp, k3d
Optional tools (command-specific): sops, velero, clusterctl, ykman, certutil, gh/glab
Components Overview
Catallaxy ships with built-in components. Each component is a self-contained module that declares configuration options and writes Kubernetes resources into deployment phases when enabled.
Components are defined in modules/lab/cluster/components/. Enable them in your cluster configuration with components.<name>.enable = true.
Component catalog
CNI
| Component | Description |
|---|---|
| cilium | eBPF-based CNI and network policy engine. Provides pod networking, service mesh, and network observability. |
Gateway
| Component | Description |
|---|---|
| gateway | Gateway API controller (Traefik). Manages ingress via HTTPRoute and TLSRoute resources. Configures TLS termination and passthrough. |
PKI
| Component | Description |
|---|---|
| cert-manager | X.509 certificate management. Automates certificate issuance and renewal using the lab CA or ACME. |
| trust-manager | Distributes CA bundles across namespaces as ConfigMaps. Ensures all services trust the lab CA. |
Observability
| Component | Description |
|---|---|
| prometheus | Metrics collection and alerting (kube-prometheus-stack). Includes Prometheus, Alertmanager, and recording/alerting rules. |
| grafana | Dashboards and visualization. Connects to Prometheus, Loki, and Tempo as data sources. Supports OIDC login via Kanidm. |
| loki | Log aggregation. Receives logs from OpenTelemetry collectors and provides LogQL query interface. |
| tempo | Distributed tracing backend. Receives traces via OTLP and integrates with Grafana. |
| otel-collector | OpenTelemetry Collector. Deployed as agent (DaemonSet) and/or gateway (Deployment) to collect and forward logs, metrics, and traces. |
Databases
| Component | Description |
|---|---|
| cnpg | CloudNativePG operator. Manages PostgreSQL clusters with automated failover, backups, and connection pooling. |
| redis-operator | Redis operator. Manages Redis instances and clusters. |
Filesystems
| Component | Description |
|---|---|
| openebs | Local persistent volume provisioner. Provides storage classes backed by node-local paths. |
| seaweedfs | Distributed object storage. Provides S3-compatible storage for backups, Loki chunks, and Tempo blocks. |
Registries
| Component | Description |
|---|---|
| zot | OCI-compliant container registry. Lightweight registry for local image caching and distribution. |
Secrets
| Component | Description |
|---|---|
| external-secrets | Syncs secrets from external providers (Vault, AWS, etc.) into Kubernetes Secrets. |
| sops | SOPS-based secret decryption. Decrypts encrypted secret files at deployment time. |
Identity
| Component | Description |
|---|---|
| kanidm | Identity provider. Provides OIDC/OAuth2 authentication, user management, and WebAuthn/TOTP support. |
| kaniop | Kanidm operator. Declaratively manages Kanidm users, groups, and OAuth2 client registrations as Kubernetes resources. |
GitOps
| Component | Description |
|---|---|
| argocd | Argo CD continuous delivery. Manages application deployments from Git repositories. Supports OIDC login via Kanidm. |
Source Control
| Component | Description |
|---|---|
| forgejo | Self-hosted Git forge. Lightweight GitHub/Gitea alternative with OAuth2 login, issue tracking, and CI integration. |
Provisioning
| Component | Description |
|---|---|
| cluster-api | Cluster API operator (CAPI). Provisions and manages Kubernetes clusters declaratively. |
| crossplane | Crossplane universal control plane. Manages cloud infrastructure (DNS, compute, storage) as Kubernetes resources. |
DNS
| Component | Description |
|---|---|
| external-dns | Synchronizes Kubernetes Gateway/Ingress resources with external DNS providers (CoreDNS, Cloudflare, Route53). |
VPN
| Component | Description |
|---|---|
| netbird | WireGuard-based mesh VPN. Provides secure connectivity between clusters and external networks. |
Backups
| Component | Description |
|---|---|
| velero | Cluster backup and restore. Supports scheduled backups to S3-compatible storage and cross-cluster migration. |
Custom
| Component | Description |
|---|---|
| custom | Deploy custom applications using components.custom.apps.<name>. Supports Helm charts, typed resources, raw YAML, and Gateway API routing without writing a full component module. See the Custom Components recipe. |
Cross-component wiring
Components expose computed values through ref attributes. These are always available, even when the component is disabled, allowing safe cross-references:
{ config, ... }:
let
certManagerRef = config.components.cert-manager.ref;
kanidmRef = config.components.kanidm.ref;
in
{
# Use certManagerRef.caBundleConfigMap, kanidmRef.oidcEndpoint, etc.
}
For cross-cluster references, use the lab argument:
{ lab, ... }:
{
components.otel-collector.exporters.otlp.endpoint =
lab.clusters.obs.components.tempo.ref.otlpGrpc;
}
See Adding Components for the full component authoring guide.
Homelab OIDC Setup
This recipe walks through standing up the example homelab with full OIDC authentication. By the end, you will have a local Kubernetes lab where ArgoCD, Grafana, and Forgejo all authenticate through Kanidm as the identity provider.
Prerequisites
- Nix with flakes enabled
- Docker (for k3d)
- Enter the dev shell:
nix develop
Step 1: Start the lab
cata --flake ./examples/labs#homelab lab up
This provisions all clusters defined in the lab (by default, a core cluster and an obs cluster via k3d), evaluates the Nix modules, renders manifests, and applies them phase by phase. The process takes several minutes on first run as Helm charts are templated and resources are deployed in dependency order.
Step 2: Trust the lab CA
cata --flake ./examples/labs#homelab lab trust --setup
The lab generates its own certificate authority. This command installs the lab CA into your system trust store so that browsers and CLI tools accept TLS certificates issued for *.homelab.test domains without warnings.
To remove the CA later:
cata --flake ./examples/labs#homelab lab trust --teardown
Step 3: Configure local DNS
cata --flake ./examples/labs#homelab lab dns --setup
This configures your local resolver so that *.homelab.test domains resolve to 127.0.0.1 (where k3d exposes its ingress). The exact mechanism depends on your OS (systemd-resolved, dnsmasq, etc.).
To remove the DNS configuration later:
cata --flake ./examples/labs#homelab lab dns --teardown
Step 4: Initialize a user account
cata --flake ./examples/labs#homelab lab ops init-user lab-admin
This resets (or creates) the lab-admin account in Kanidm and prints a temporary password. The init-user command is a lab ops command – it understands the lab topology. It knows which cluster runs Kanidm, which namespace the pod lives in, and how to exec into it. You do not need to figure out contexts or namespaces yourself.
Lab ops commands are defined in the lab’s Nix configuration and have full access to component refs:
lab.ops.commands.init-user = {
description = "Reset a kanidm account password";
package = pkgs.writeShellApplication {
name = "init-user";
runtimeInputs = [ pkgs.kubectl ];
text = ''
kubectl --context k3d-core exec -n ${kanidmRef.namespace} kanidm-default-0 -- \
kanidmd recover-account "$1"
'';
};
};
Step 5: Log in to Kanidm
Open https://idm.homelab.test in your browser. Log in with the lab-admin username and the temporary password from the previous step. You will be prompted to set a new password and configure WebAuthn or TOTP.
Step 6: Access services via OIDC
With your Kanidm account set up, all OIDC-enabled services authenticate through it:
| Service | URL | Notes |
|---|---|---|
| ArgoCD | https://argocd.homelab.test | Click “Log in via Kanidm” |
| Grafana | https://grafana.homelab.test | Click “Sign in with Kanidm” |
| Forgejo | https://git.homelab.test | Click the Kanidm OAuth2 option |
Each service has its OAuth2 client registered in Kanidm automatically via the kaniop operator. Group memberships in Kanidm map to roles in each service – for example, members of the grafana-editors group get the Editor role in Grafana.
How it works
The OIDC integration is wired through cross-component references:
- cert-manager issues TLS certificates for all services using the lab CA.
- kanidm runs as the identity provider with its own TLS certificate.
- kaniop manages OAuth2 client registrations in Kanidm declaratively, creating client secrets as Kubernetes Secrets.
- Each service (ArgoCD, Grafana, Forgejo) references the Kanidm OIDC endpoint and its client secret via component
refattributes.
Because everything is evaluated at Nix build time, the URLs, namespaces, and secret names are consistent and type-checked. There is no manual coordination between services.
Troubleshooting
Browser shows certificate warnings: Run cata lab trust --setup and restart your browser.
DNS does not resolve: Run cata lab dns --setup. On systemd-resolved systems, you may need to restart the resolver.
OIDC login fails: Check that Kanidm is running and the OAuth2 clients are registered:
kubectl --context k3d-core get oauth2clients -n kanidm
Temporary password expired: Re-run cata lab ops init-user lab-admin to get a fresh one.
Backup and Restore
Catallaxy uses Velero for cluster backup and restore in it’s example. However you can extend catallaxy to use whatever k8s backup strategy you want. For local development, backups are stored in SeaweedFS (S3-compatible). For production, Velero supports AWS S3, GCP Cloud Storage, and Azure Blob Storage.
Enabling Backups
Enable Velero and a storage backend on the cluster that holds your stateful workloads:
# aspects/backups.nix
{ ... }:
{
components.seaweedfs.enable = true;
components.velero = {
enable = true;
local.enable = true; # SeaweedFS-backed storage for local dev
schedules.daily = {
schedule = "0 2 * * *";
ttl = "168h"; # 7 days
};
};
}
Deploy with cata lab up or cata lab apply. Velero will start taking scheduled backups automatically.
Cloud Storage (Production)
For production, point Velero at a real S3 bucket:
components.velero = {
enable = true;
backupStorageLocation = {
provider = "aws";
bucket = "my-velero-backups";
s3 = {
region = "us-east-1";
};
};
};
Using Velero
Backups are managed directly via the velero CLI or through lab ops commands.
On-Demand Backup
# Via ops commands (if configured in your lab)
cata lab ops backup create
# Or directly via velero CLI
velero backup create my-backup --include-namespaces forgejo,kanidm
List and Inspect
velero backup get
velero backup describe my-backup
velero backup logs my-backup
Restore
velero restore create --from-backup my-backup
velero restore create --from-backup my-backup --include-namespaces forgejo
Schedules
velero schedule get
velero schedule trigger daily
Cross-Cluster Migration
Migrate workloads between clusters by backing up on one and restoring on another. Both clusters must have Velero configured with access to the same backup storage location.
# On source cluster
velero backup create migration-backup
# On target cluster
velero restore create --from-backup migration-backup
Management Cluster Pivot
For environments with cloud management clusters, catallaxy handles the pivot automatically during lab up when a cluster self-provisions (declares itself in its own Crossplane kubernetesClusters). The planner generates bootstrap → pivot → destroy steps. See Bootstrap & Pivot for details.
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
| Option | Default | Description |
|---|---|---|
gateway.enable | false | Generate a Gateway API route |
gateway.mode | "terminate" | "terminate" for HTTPRoute, "passthrough" for TLSRoute |
gateway.domain | "" | Hostname for the route |
gateway.serviceName | app name | Backend service name |
gateway.servicePort | 80 | Backend 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
| Option | Default | Description |
|---|---|---|
enable | true | Whether to deploy this app |
phase | "apps" | Deployment phase |
namespace | app name | Kubernetes namespace |
createNamespace | true | Auto-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
refwiring. - 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
refattributes. - The component has complex configuration options that benefit from the NixOS module type system.
- You intend to contribute the component upstream.
Secrets Management
Catallaxy uses a three-layer model for secrets: stores, managed secrets, and projections.
The Model
Stores → Where encrypted values are stored (one SOPS file per store)
Managed Secrets → Source-of-truth keys that reference a store
Projections → How managed secrets map to K8s Secrets per cluster/namespace
Setup
1. Install SOPS and age
SOPS is included in the devshell. For age keys:
# Generate an age key (or use a YubiKey)
age-keygen -o ~/.config/sops/age/keys.txt
# For YubiKey:
age-plugin-yubikey # Follow prompts to set up
2. Configure .sops.yaml
Create .sops.yaml at the repo root with creation rules matching your store paths:
creation_rules:
# Prod secrets — encrypt with your age key
- path_regex: secrets/homelab\.prod/.*\.enc\.yaml$
age: age1...your-public-key...
# Local dev secrets
- path_regex: secrets/homelab\.local/.*\.enc\.yaml$
age: age1...your-public-key...
3. Declare stores and managed secrets
In your lab config:
# Stores — each becomes one SOPS file
lab.secrets.stores.cloud-creds = { backend = "sops"; };
# Managed secrets — source-of-truth keys
lab.secrets.managed = {
do-token = {
store = "cloud-creds";
keys.token = { }; # Manual entry via secrets edit
};
cf-token = {
store = "cloud-creds";
keys.token = { };
};
db-password = {
store = "cloud-creds";
keys.password = {
generator = "alphanumeric"; # Auto-generated
length = 32;
};
};
};
4. Generate and edit secrets
# Generate SOPS files (creates placeholders, auto-generates where configured)
cata secrets generate
# Edit a store to fill in manual values
cata secrets edit cloud-creds
# List all secrets and their status
cata secrets list
Projections
Projections map managed secrets into Kubernetes Secrets with optional transforms:
# In a cluster config:
secrets.projections.cloudflare-api-token = {
source = "cf-token"; # From lab.secrets.managed
namespace = "cert-manager"; # Target K8s namespace
phase = "operators"; # Injected before this phase deploys
keys.api-token.from = "token"; # Key mapping: K8s key ← managed key
};
secrets.projections.db-credentials = {
source = "db-password";
namespace = "forgejo";
phase = "databases";
keys = {
password.from = "password";
credentials = {
from = "password";
transform = "json-wrap"; # Wraps as {"password": "value"}
jsonKey = "password";
};
};
};
Transforms
| Transform | Description |
|---|---|
none (default) | Passthrough — value as-is |
base64 | Base64-encode the value |
json-wrap | Wrap as JSON: {"<jsonKey>": "<value>"} |
Phase Ordering
Projections must be in a phase that runs before or during the phase of components that reference them. A Nix assertion validates this at build time:
Projection 'my-secret' is in phase 'infrastructure' (order 30)
but namespace 'my-ns' has components in phase 'operators' (order 10).
The secret won't exist when the component deploys.
The projection-ref lint check also validates that secretKeyRef names match declared projection names.
Per-Environment Keys
Use different age keys per environment in .sops.yaml:
creation_rules:
- path_regex: secrets/.*\.prod/.*
age: age1...prod-yubikey...
- path_regex: secrets/.*\.staging/.*
age: age1...staging-key...
- path_regex: secrets/.*\.local/.*
age: age1...dev-key...
YubiKey Workflow
With age-plugin-yubikey, SOPS prompts for the YubiKey PIN during decryption. During lab up, secrets are decrypted once (during the ensure-secrets step) and cached in memory for all subsequent cluster deployments. This avoids repeated PIN prompts when Crossplane provisioning creates long gaps between cluster deploys.
CLI Commands
cata secrets generate # Generate SOPS files for all stores
cata secrets edit <store> # Decrypt, edit, re-encrypt a store
cata secrets decrypt <store> # Decrypt to stdout
cata secrets rotate <store> # Rotate encryption keys
cata secrets list # Show stores, managed secrets, and projections
Operational Runbook
Lab Lifecycle
Starting a Lab
cata lab up # Deploy everything
cata lab plan # Preview the deployment plan
cata lab plan --teardown # Preview the teardown plan
Updating a Lab
cata apply <cluster> # Apply all phases to a cluster
cata apply <cluster> --phase operators # Apply a single phase
cata lab apply # Apply to all clusters in a lab
Stopping a Lab
cata lab down # Stop clusters (preserves state, restartable with lab up)
cata lab destroy # Delete everything: clusters, cloud resources, services, network
Troubleshooting
ProgressDeadlineExceeded
Symptom: kapp reports a deployment stuck in ProgressDeadlineExceeded on re-runs.
Cause: A previous deploy failed (e.g., missing secret), leaving the deployment in a stale error state. On re-run, kapp sees no spec change (noop) and fails on the stale status.
Fix: The CLI auto-restarts stuck deployments before each kapp deploy. If the underlying issue is fixed (e.g., secret now exists), re-running lab up should resolve it automatically.
Secret Not Found (CreateContainerConfigError)
Symptom: CreateContainerConfigError: secret "X" not found
Possible causes:
- Projection phase too late: The secret projection is in a phase that runs after the component. Check with
cata lab lint— theprojection-refcheck catches this. - SOPS decryption failed: YubiKey wasn’t available or PIN wasn’t entered. Check the
ensure-secretsstep output. - Store file missing: Run
cata secrets generatethencata secrets edit <store>.
ACME Certificate Not Issued
Symptom: Certificate stuck in False status, challenges pending.
Check:
kubectl get challenges -A
kubectl describe challenge <name> -n <ns>
Common causes:
- API token missing Zone:Read: Cloudflare token needs both
Zone:ReadandDNS:Edit - Wrong domain filter:
domainFiltersmust be the Cloudflare zone name (e.g.,praxioticsystems.com), not a subdomain - DNS negative cache: NXDOMAIN cached for 30 minutes (SOA minimum TTL). Wait or use a different resolver to verify.
Crossplane Resource Not Ready
Symptom: wait-for-resources stuck, managed resources show SYNCED=False.
Check:
kubectl get managed # See all managed resources
kubectl describe <kind>/<name> # Check status.conditions
kubectl get providerconfig # Verify credentials
Common causes:
- Wrong credentials: Check the secret referenced by ProviderConfig
- API quota exceeded: DigitalOcean droplet limit reached
- Provider not healthy:
kubectl get providers— check HEALTHY status
Backup & Restore
Creating a Backup
Velero schedules are configured per-cluster. To trigger a manual backup:
cata lab ops backup create
Restoring from Backup
velero restore create --from-backup <backup-name>
Checking Backup Status
velero backup get
velero schedule get
Certificate Management
ACME (Production)
Certificates are auto-renewed by cert-manager 30 days before expiry. No manual action needed.
To force renewal:
kubectl delete certificate <name> -n <ns>
# cert-manager will re-issue automatically
Self-Signed CA (Local Dev)
The lab CA is generated during lab up and distributed via trust-manager. Certificates are valid for 1 year by default.
CLI Commands
The cata CLI orchestrates runtime operations for Catallaxy labs. It evaluates Nix expressions, applies manifests to clusters, and manages secrets, PKI, and images.
Most commands require a --flake argument pointing to your lab flake:
cata --flake '.#homelab.local' <command>
Lab Lifecycle
cata lab up
Provision all clusters, render manifests, and apply them phase by phase.
cata lab up
cata lab down
Stop lab clusters. Preserves state — clusters can be restarted with lab up.
cata lab down
cata lab destroy
Destroy lab completely — deletes clusters, cloud resources, services, and network. Not reversible.
cata lab destroy
cata lab init
Initialize lab infrastructure without applying manifests.
cata lab init
cata lab status
Show the status of all clusters and services.
cata lab status
cata lab list
List all labs defined in the flake.
cata lab list
cata lab plan
Show the computed deployment plan without executing.
cata lab plan
cata lab plan --teardown # show teardown plan
cata lab lint
Validate rendered manifests against property checks.
cata lab lint
cata lab lint --skip image-pin,crd-schema # skip specific checks
cata lab lint --path /nix/store/...-lab-* # lint a pre-built package
cata lab apply
Apply manifests to all clusters without provisioning.
cata lab apply
cata lab apply --phase operators # specific phase
Lab Publishing
cata lab publish
Render manifests and push to a Git repository for GitOps consumption.
cata lab publish
cata lab publish --pr # create a pull request
cata lab publish --dry-run # preview without pushing
Lab Ops
cata lab ops <args...>
Run lab-defined operational commands.
cata lab ops idm init-user lab-admin
cata lab ops database shell
Local Environment
cata lab dns
Configure local DNS resolution for lab domains.
cata lab dns --setup
cata lab dns --teardown
cata lab trust
Install or remove the lab CA from the system trust store.
cata lab trust --setup
cata lab trust --teardown
cata lab trust --export # print CA PEM to stdout
Cluster Lifecycle
cata cluster up
Provision and apply manifests to a single cluster.
cata cluster up core
cata cluster down
Stop a single cluster (alias: cluster destroy).
cata cluster down core
Apply
cata apply <cluster>
Apply manifests to a cluster with fine-grained control.
cata apply core
cata apply core --phase networking
cata apply core --dry-run
cata apply core --force # bypass GitOps strategy check
PKI
cata pki init
Initialize the PKI CA for a cluster (generates root CA if needed).
cata pki init core
cata pki issue <user>
Issue a client certificate for a user.
cata pki issue admin
cata pki provision <user>
Write a certificate to a YubiKey PIV slot.
cata pki provision admin
cata pki list
List CA and certificate status.
cata pki list core
cata pki kubeconfig <user>
Generate a kubeconfig entry using the client certificate.
cata pki kubeconfig admin
Secrets
cata secrets generate
Generate SOPS-encrypted secret files for all stores.
cata secrets generate
cata secrets edit <store>
Decrypt, edit, and re-encrypt a secrets store.
cata secrets edit cloud-creds
cata secrets decrypt <store>
Decrypt a store to stdout.
cata secrets decrypt cloud-creds
cata secrets encrypt <file>
Encrypt a plaintext file.
cata secrets encrypt secrets.yaml
cata secrets encrypt secrets.yaml --output secrets.enc.yaml
cata secrets rotate <store>
Rotate encryption keys on a SOPS file.
cata secrets rotate cloud-creds
cata secrets list
Show all stores, managed secrets, and projections.
cata secrets list
Images
cata images list
List all container images used by a lab.
cata images list
cata images mirror
Mirror lab images to a target registry using crane.
cata images mirror --registry ghcr.io/my-org
cata images mirror --registry ghcr.io/my-org --dry-run
cata images prefetch
Prefetch lab images into a local registry (e.g., Zot).
cata images prefetch --registry localhost:5050
Kubeconfig
cata kubeconfig sync
Sync kubeconfig entries for lab clusters.
cata kubeconfig sync
Code Generation
cata generate
Generate Kubernetes API types from OpenAPI specs and CRDs (development use).
nix run .#generate-k8s-types
Module Options
Auto-generated reference for all catallaxy module options. Options are split across pages by category to keep each page fast to load.
Lab options
Top-level lab configuration: name, environment, CD strategy, DNS, networking, ingress, registry, and ops commands.
Cluster options
Per-cluster configuration nested under lab.clusters.<name>: Kubernetes
settings, provisioners, phases, authentication, and storage.
Component options
Each component declares options under lab.clusters.<name>.components.<name>.
Pages are grouped by category:
| Category | Components |
|---|---|
| CNI | Cilium |
| Gateway and DNS | Gateway, External DNS |
| PKI | cert-manager, trust-manager |
| Observability | Prometheus, Grafana, Loki, Tempo, OTEL Collector |
| Databases | CloudNativePG, Redis Operator |
| Filesystems | OpenEBS, SeaweedFS |
| Secrets | External Secrets, SOPS |
| Identity | Kanidm, Kaniop, OIDC |
| GitOps | ArgoCD |
| Source Control | Forgejo |
| Provisioning | Cluster API, Crossplane |
| Other | Velero, Netbird, Zot, Custom |
How options are structured
Every component follows the same pattern:
options.components.<name> = {
enable = mkEnableOption "<Name>";
phase = mkOption { default = "<phase>"; };
namespace = mkOption { default = "<namespace>"; };
chart = mkOption { ... };
ref = mkOption { readOnly = true; };
};
The ref attribute provides computed values for cross-component wiring. It is
always set, even when the component is disabled, so other components can
reference it safely.
Lab Options
Options for configuring the lab environment, CD strategy, DNS, networking, and operations.
bgpRouter.asn
BGP Autonomous System Number for the router
Type: signed integer
Default: 65000
Declared in: modules/lab/bgp-router.nix
bgpRouter.containerName
Docker container name for the BGP router
Type: string
Default: "catallaxy-router"
Declared in: modules/lab/bgp-router.nix
bgpRouter.enable
Whether to enable Lab BGP router (FRRouting) for LoadBalancer IP advertisement.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/bgp-router.nix
bgpRouter.image
FRRouting container image
Type: string
Default: "frrouting/frr:latest"
Declared in: modules/lab/bgp-router.nix
bgpRouter.lbPool
IP pool CIDR for LoadBalancer service allocation
Type: string
Default: "172.19.200.0/24"
Declared in: modules/lab/bgp-router.nix
bgpRouter.out.service
Computed container service definition for the BGP router
Type: attribute set
Default: { }
Declared in: modules/lab/bgp-router.nix
bgpRouter.peerASN
BGP ASN for Cilium nodes (peers)
Type: signed integer
Default: 65001
Declared in: modules/lab/bgp-router.nix
bgpRouter.peerAddress
IP address where the BGP router is reachable by Cilium nodes (Docker network gateway)
Type: string
Default: "172.19.0.1"
Declared in: modules/lab/bgp-router.nix
cd.argocd.repoUrl
Git repository URL for manifest storage
Type: string
Default: ""
Declared in: modules/lab/types.nix
cd.argocd.targetBranch
Git branch to commit rendered manifests to
Type: string
Default: "main"
Declared in: modules/lab/types.nix
cd.clusterPaths
Per-cluster targetPath overrides. Key = cluster name, value = path in repo. Default: manifests/
Type: attribute set of string
Default: { }
Declared in: modules/lab/types.nix
cd.fleet.repoUrl
Git repository URL for manifest storage
Type: string
Default: ""
Declared in: modules/lab/types.nix
cd.fleet.targetBranch
Git branch to commit rendered manifests to
Type: string
Default: "main"
Declared in: modules/lab/types.nix
cd.git.branch
Target branch for manifest publishing
Type: string
Default: "main"
Declared in: modules/lab/types.nix
cd.git.path
Subdirectory within the repo for manifests (empty = repo root)
Type: string
Default: ""
Declared in: modules/lab/types.nix
cd.git.prBaseBranch
Base branch for PRs (the branch to merge into)
Type: string
Default: "main"
Declared in: modules/lab/types.nix
cd.git.prEnabled
Create a PR/MR instead of pushing directly to the target branch
Type: boolean
Default: false
Declared in: modules/lab/types.nix
cd.git.provider
Git provider for PR/MR creation
Type: one of "github", "gitlab", "forgejo"
Default: "github"
Declared in: modules/lab/types.nix
cd.git.repo
Git repository URL for publishing rendered manifests (e.g. git@github.com:org/manifests.git)
Type: string
Default: ""
Declared in: modules/lab/types.nix
cd.kapp.waitTimeout
Timeout waiting for resources to reconcile
Type: string
Default: "10m"
Declared in: modules/lab/types.nix
cd.strategy
CD strategy for delivering manifests to all clusters:
- kapp: Direct apply via kapp (fast, no git, ideal for local dev)
- argocd: Render manifests to git, ArgoCD syncs from there
- fleet: Render manifests to git, Fleet syncs from there
Type: one of "kapp", "argocd", "fleet"
Default: "kapp"
Declared in: modules/lab/types.nix
clusters
Cluster configurations. Each cluster is provisioned directly by the CLI (e.g. via k3d for local dev). Any cluster can optionally enable CAPI to manage external clusters.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/types.nix
dns.containerName
Docker container name for the DNS server
Type: string
Default: "catallaxy-dns"
Declared in: modules/lab/dns.nix
dns.enable
Whether to enable Lab DNS server (Knot DNS with RFC2136 for ExternalDNS).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/dns.nix
dns.hostPort
Host-mapped port for the DNS server (for host access). Avoids 5353 which conflicts with mDNS.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 5354
Declared in: modules/lab/dns.nix
dns.image
Knot DNS container image
Type: string
Default: "cznic/knot:latest"
Declared in: modules/lab/dns.nix
dns.out.dnsInfo
DNS server info for host resolver configuration
Type: attribute set
Default: { }
Declared in: modules/lab/dns.nix
dns.out.service
Computed container service definition for the lab DNS server
Type: attribute set
Default: { }
Declared in: modules/lab/dns.nix
dns.port
Port for the DNS server (as seen from clusters, defaults to hostPort)
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 5354
Declared in: modules/lab/dns.nix
dns.server
IP address where the DNS server is reachable from clusters (Docker gateway by default)
Type: string
Default: "172.19.0.1"
Declared in: modules/lab/dns.nix
dns.tsigKeyname
TSIG key name for RFC2136 dynamic updates
Type: string
Default: "externaldns-key"
Declared in: modules/lab/dns.nix
dns.tsigSecret
Base64-encoded TSIG secret (pre-generated for local dev)
Type: string
Default: "kp4bgnFAVCmajGIqOW7rj0MNwRNZHBqMvYaLTwzPHgI="
Declared in: modules/lab/dns.nix
dns.tsigSecretAlg
TSIG algorithm
Type: string
Default: "hmac-sha256"
Declared in: modules/lab/dns.nix
dns.zone
DNS zone for the lab (defaults to ‘
Type: string
Default: "docs-placeholder.test"
Declared in: modules/lab/dns.nix
environment
Lab environment. Components can adjust defaults based on this:
- development: minimal replicas, relaxed resource limits, self-signed TLS
- staging: moderate replicas, production-like config, self-signed or ACME TLS
- production: HA replicas, strict resource limits, ACME TLS, destructive ops require –force
Type: one of "development", "staging", "production"
Default: "development"
Declared in: modules/lab/types.nix
images.allowedRegistries
When non-empty, the lint check warns about images from registries not in this list. Example: [“ghcr.io” “registry.k8s.io” “docker.io”]
Type: list of string
Default: [ ]
Declared in: modules/lab/images.nix
images.pins
Pinned container images. Each pin declares an image with optional tag and digest.
Components can reference pins via lab.images.pins.<name>.ref to get
the full image reference string.
Example: lab.images.pins.grafana = { image = “docker.io/grafana/grafana”; tag = “11.4.0”; digest = “sha256:abc123…”; };
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/images.nix
images.pins.<name>.digest
Image digest (e.g., sha256:abc123…). Immutable — ensures reproducibility.
Type: null or string
Declared in: modules/lab/images.nix
images.pins.<name>.image
Full image path (e.g., docker.io/grafana/grafana)
Type: string
Declared in: modules/lab/images.nix
images.pins.<name>.ref
Computed full image reference (image:tag@digest)
Type: string
Declared in: modules/lab/images.nix
images.pins.<name>.tag
Image tag (e.g., 11.4.0). Mutable — use digest for reproducibility.
Type: null or string
Declared in: modules/lab/images.nix
images.requireDigest
When true, the lint check errors on container images without digest pins. Use this to enforce reproducible deployments.
Type: boolean
Default: false
Declared in: modules/lab/images.nix
lint.checks
Custom lint checks that run on rendered manifests.
Each check is a shell command executed per YAML file.
Checks run alongside built-in checks during cata lab lint.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/lint.nix
lint.checks.<name>.command
Shell command to execute per YAML file. Environment variables: $FILE — path to the YAML manifest file $CLUSTER — name of the cluster being checked Exit 0 = pass, non-zero = fail. Stdout = diagnostic message (shown to user on failure).
Type: string
Declared in: modules/lab/lint.nix
lint.checks.<name>.description
Human-readable description of what this check validates
Type: string
Declared in: modules/lab/lint.nix
lint.checks.<name>.severity
Error = fails the lint, Warning = reported but doesn’t fail
Type: one of "error", "warning"
Default: "warning"
Declared in: modules/lab/lint.nix
name
Unique name for this lab
Type: string
Example: "homelab"
Declared in: modules/lab/types.nix
network.dockerSubnet
Subnet for the lab
Type: string
Default: "172.19.0.0/16"
Declared in: modules/lab/network.nix
ops.commands
Lab-global operational commands. These are not cluster-specific and appear directly in the ops tool under their category.
Components contribute cluster-scoped commands via the cluster-level
ops.<name> option. Same-named commands from different clusters
are automatically merged (enum options get their values unioned).
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/ops.nix
ops.commands.<name>.args
Positional arguments
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/ops.nix
ops.commands.<name>.args.*.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/ops.nix
ops.commands.<name>.args.*.name
This option has no description.
Type: string
Declared in: modules/lab/ops.nix
ops.commands.<name>.args.*.required
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/ops.nix
ops.commands.<name>.category
Subcommand group (e.g. ‘backup’, ‘database’)
Type: string
Default: "general"
Declared in: modules/lab/ops.nix
ops.commands.<name>.description
One-line description shown in help
Type: string
Declared in: modules/lab/ops.nix
ops.commands.<name>.options
Named options (flags)
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/ops.nix
ops.commands.<name>.options.<name>.default
This option has no description.
Type: null or string
Declared in: modules/lab/ops.nix
ops.commands.<name>.options.<name>.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/ops.nix
ops.commands.<name>.options.<name>.required
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/ops.nix
ops.commands.<name>.options.<name>.type
This option has no description.
Type: one of "string", "enum", "bool"
Default: "string"
Declared in: modules/lab/ops.nix
ops.commands.<name>.options.<name>.values
Valid values for enum type
Type: list of string
Default: [ ]
Declared in: modules/lab/ops.nix
ops.commands.<name>.package
Package providing the command binary
Type: package
Declared in: modules/lab/ops.nix
ops.out.tool
Generated lab operations CLI tool (null if no commands defined)
Type: null or package
Declared in: modules/lab/ops.nix
out.allClusters
Computed attrset of all clusters in the lab. Keys are cluster names, values are evaluated cluster configs. Use this for cross-cluster references.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/out.nix
out.bootstrapManifests
Per-cluster kapp-format manifests for direct-apply bootstrap.
When strategy is kapp, this equals manifests. Otherwise renders
with kapp for use by lab up (which always direct-applies).
Type: attribute set of package
Default: { }
Declared in: modules/lab/out.nix
out.cliConfig
JSON-serializable lab configuration for the CLI.
Contains the fields that cata lab commands need:
management, clusterNames, services, network, registryPort, dnsInfo.
Type: attribute set
Default: { }
Declared in: modules/lab/out.nix
out.clusterNames
List of all cluster names in the lab
Type: list of string
Default: [ ]
Declared in: modules/lab/out.nix
out.deploymentPlan
Computed deployment plan — an ordered list of typed steps for the CLI to execute.
Inspect with cata lab plan.
Type: list of (submodule)
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.bootstrapContext
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.cluster
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.clusters
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.ephemeral
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.name
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.provisioner
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.resources
This option has no description.
Type: list of attribute set of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.skipIfReachable
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.stores
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.target
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.targetContext
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.deploymentPlan.*.type
This option has no description.
Type: string
Declared in: modules/lab/planner.nix
out.labNamespaces
Per-cluster list of lab-created namespaces (before prefix application). Used by checks to verify prefix completeness.
Type: attribute set of list of string
Default: { }
Declared in: modules/lab/out.nix
out.manifests
Per-cluster rendered manifest packages. Each package contains the strategy-specific directory layout (kapp, argocd, or fleet) with human-readable YAML manifests.
Type: attribute set of package
Default: { }
Declared in: modules/lab/out.nix
out.package
Single package containing all lab outputs. Includes metadata.json (pretty-printed) and manifests/ directory with symlinks to each cluster’s rendered manifests.
Type: package
Declared in: modules/lab/out.nix
out.teardownPlan
Computed teardown plan — an ordered list of typed steps for safe lab destruction.
Inspect with cata lab plan --teardown.
Type: list of (submodule)
Declared in: modules/lab/planner.nix
out.teardownPlan.*.bootstrapContext
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.cluster
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.clusters
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.teardownPlan.*.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/planner.nix
out.teardownPlan.*.ephemeral
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/planner.nix
out.teardownPlan.*.name
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.provisioner
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.resources
This option has no description.
Type: list of attribute set of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.teardownPlan.*.skipIfReachable
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.stores
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/planner.nix
out.teardownPlan.*.target
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.targetContext
This option has no description.
Type: null or string
Declared in: modules/lab/planner.nix
out.teardownPlan.*.type
This option has no description.
Type: string
Declared in: modules/lab/planner.nix
prefix
Global name prefix applied to all rendered output. Use for multi-tenancy on shared clusters or running multiple lab instances. When set, resource names, namespaces, fleet bundles, and ArgoCD apps are all prefixed. Empty string = disabled.
Type: string
Default: ""
Example: "dev"
Declared in: modules/lab/types.nix
proxy.containerName
Docker container name for the ingress
Type: string
Default: "catallaxy-ingress"
Declared in: modules/lab/proxy.nix
proxy.enable
Whether to enable Lab ingress (HAProxy for domain-based routing to k3d clusters).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/proxy.nix
proxy.httpPort
Host port for HTTP (redirects to HTTPS)
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 80
Declared in: modules/lab/proxy.nix
proxy.httpsPort
Host port for HTTPS
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 443
Declared in: modules/lab/proxy.nix
proxy.image
HAProxy container image
Type: string
Default: "haproxy:3.1-alpine"
Declared in: modules/lab/proxy.nix
proxy.out.service
Computed container service definition for the lab ingress
Type: attribute set
Default: { }
Declared in: modules/lab/proxy.nix
registry.containerName
Docker container name for the registry
Type: string
Default: "catallaxy-registry"
Declared in: modules/lab/registry.nix
registry.enable
Whether to enable Lab registry for image caching (Zot OCI registry as pull-through cache).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/registry.nix
registry.image
Zot registry container image
Type: string
Default: "ghcr.io/project-zot/zot-linux-amd64:v2.1.1"
Declared in: modules/lab/registry.nix
registry.port
Host port for the registry
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 5050
Declared in: modules/lab/registry.nix
registry.service
Computed container service definition for the lab registry
Type: attribute set
Default: { }
Declared in: modules/lab/registry.nix
secrets.managed
Managed secrets. Each declares source keys that live in a store.
Components project these into Kubernetes Secrets via
cluster-level secrets.projections.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/secrets.nix
secrets.managed.<name>.keys
Source key definitions — these appear in the SOPS file
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/secrets.nix
secrets.managed.<name>.keys.<name>.generator
Generator for this key’s value. null means the value is set
manually via cata secrets edit.
Type: null or one of "base64", "hex", "alphanumeric", "uuid"
Declared in: modules/lab/secrets.nix
secrets.managed.<name>.keys.<name>.length
Length of generated value
Type: null or (positive integer, meaning >0)
Declared in: modules/lab/secrets.nix
secrets.managed.<name>.store
Name of the secret store this secret belongs to
Type: string
Declared in: modules/lab/secrets.nix
secrets.stores
Secret stores. Each store maps to one SOPS file (or one Vault path).
SOPS files are at: secrets/
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/secrets.nix
secrets.stores.<name>.backend
Storage backend:
- sops: encrypted YAML files in git
- vault: HashiCorp Vault (future)
- external: managed outside catallaxy
Type: one of "sops", "vault", "external"
Default: "sops"
Declared in: modules/lab/secrets.nix
Cluster Options
Options for configuring individual clusters within a lab, including Kubernetes settings, provisioners, phases, and authentication.
All options are under lab.clusters.<name>.
cluster.certSANs
Extra Subject Alternative Names added to CAPI cluster API server certificates. Includes 127.0.0.1 so kubeconfigs rewritten for host access work with valid TLS.
Type: list of string
Default:
[
"127.0.0.1"
"localhost"
]
Declared in: modules/lab/cluster/types.nix
cluster.kubernetes.controlPlanes
Number of control plane nodes
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/types.nix
cluster.kubernetes.distribution
Kubernetes distribution to use
Type: one of "talos", "k3s", "k8s"
Default: "talos"
Declared in: modules/lab/cluster/types.nix
cluster.kubernetes.version
Kubernetes API version for type generation (e.g., ‘1.31’)
Type: string
Default: "1.31"
Declared in: modules/lab/cluster/types.nix
cluster.kubernetes.workers
Number of worker nodes
Type: unsigned integer, meaning >=0
Default: 1
Declared in: modules/lab/cluster/types.nix
cluster.name
Unique name for this cluster
Type: string
Example: "local"
Declared in: modules/lab/cluster/types.nix
cluster.network.podSubnet
Pod network CIDR
Type: string
Default: "10.244.0.0/16"
Declared in: modules/lab/cluster/types.nix
cluster.network.serviceSubnet
Service network CIDR
Type: string
Default: "10.96.0.0/12"
Declared in: modules/lab/cluster/types.nix
cluster.out.phaseOrder
Phase names sorted by deployment order
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/out.nix
cluster.out.phases
Computed phases with rendered manifest packages. Each entry has: order, dependsOn, keepResources, pruneStrategy, waitForReady, timeout, package (derivation).
Type: raw value
Default: { }
Declared in: modules/lab/cluster/out.nix
cluster.out.sbom
Software bill of materials
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/out.nix
cluster.out.topology
Computed topology/network map
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/out.nix
cluster.provider
Computed provider category (derived from cluster.provisioner)
Type: one of "docker", "crossplane", "external"
Declared in: modules/lab/cluster/types.nix
cluster.provisioner
How this cluster is provisioned:
- k3d: k3s-in-Docker (local development)
- talos: Talos-in-Docker (local development)
- crossplane: Provisioned via Crossplane from another cluster
- external: Pre-existing cluster, just configure it
Type: one of "k3d", "talos", "crossplane", "external"
Default: "k3d"
Declared in: modules/lab/cluster/types.nix
cluster.ref.kubeContext
Kubernetes context name for kubectl/velero/etc. Set by provisioner modules.
Type: string
Declared in: modules/lab/cluster/types.nix
cluster.security.auditLogging.enable
Enable Kubernetes API server audit logging. Provisioner-specific.
Type: boolean
Default: false
Declared in: modules/lab/cluster/types.nix
cluster.security.networkPolicies.enable
Generate default-deny NetworkPolicies for lab namespaces. Components add allow rules.
Type: boolean
Default: false
Declared in: modules/lab/cluster/types.nix
cluster.security.podSecurity.default
Default PSA level for lab namespaces. Components can override per-namespace.
Type: one of "restricted", "baseline", "privileged"
Default: "restricted"
Declared in: modules/lab/cluster/types.nix
cluster.security.podSecurity.enable
Apply Pod Security Admission labels to lab-managed namespaces
Type: boolean
Default: false
Declared in: modules/lab/cluster/types.nix
cluster.security.podSecurity.namespaceOverrides
Per-namespace PSA level overrides (e.g., kube-system = privileged)
Type: attribute set of (one of "restricted", "baseline", "privileged")
Default: { }
Declared in: modules/lab/cluster/types.nix
cluster.talos.cniNone
Disable built-in CNI (for Cilium)
Type: boolean
Default: true
Declared in: modules/lab/cluster/types.nix
cluster.talos.kubeProxyDisabled
Disable kube-proxy (for Cilium kube-proxy replacement)
Type: boolean
Default: true
Declared in: modules/lab/cluster/types.nix
cluster.talos.version
Talos version
Type: string
Default: "v1.13.0"
Declared in: modules/lab/cluster/types.nix
compose
This option has no description.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster
databases.postgres
This option has no description.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster
databases.redis
This option has no description.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster
lifecycle.teardown
Ordered teardown steps executed before cluster deprovisioning
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster
lifecycle.teardown.*.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster
lifecycle.teardown.*.name
Step name for display
Type: string
Declared in: modules/lab/cluster
lifecycle.teardown.*.order
Execution order (lower = first)
Type: signed integer
Default: 0
Declared in: modules/lab/cluster
lifecycle.teardown.*.package
Script to execute for this step
Type: package
Declared in: modules/lab/cluster
lifecycle.teardown.*.waitTimeout
How long to wait for completion
Type: string
Default: "5m"
Declared in: modules/lab/cluster
ops
Operational commands contributed by components (auto-collected by lab.ops)
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster
ops.<name>.args
Positional arguments
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster
ops.<name>.args.*.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster
ops.<name>.args.*.name
This option has no description.
Type: string
Declared in: modules/lab/cluster
ops.<name>.args.*.required
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster
ops.<name>.category
Subcommand group (e.g. ‘backup’, ‘database’)
Type: string
Default: "general"
Declared in: modules/lab/cluster
ops.<name>.description
This option has no description.
Type: string
Declared in: modules/lab/cluster
ops.<name>.options
Named options (flags) for this command
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster
ops.<name>.options.<name>.default
This option has no description.
Type: null or string
Declared in: modules/lab/cluster
ops.<name>.options.<name>.description
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster
ops.<name>.options.<name>.required
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster
ops.<name>.options.<name>.type
This option has no description.
Type: one of "string", "enum", "bool"
Default: "string"
Declared in: modules/lab/cluster
ops.<name>.options.<name>.values
Valid values for enum type
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster
ops.<name>.package
This option has no description.
Type: package
Declared in: modules/lab/cluster
phases
Not all kubernetes resources can be installed at once. There is an ordering to it. Phases are the mechanism to declare that a bundle has a dependency on another.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles
Set of bundles that belong in this phase.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.createNamespaces
Namespaces to create for this phase
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts
Helm charts to render for this phase. Charts are rendered at build time using helm template, with optional kustomize patching.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.chart
Helm chart derivation
Type: package
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.createNamespace
Whether to create the namespace if it doesn’t exist
Type: boolean
Default: true
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.extraOpts
Extra options to pass to helm template
Type: list of string
Default:
[
"--skip-tests"
]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.kustomize
Kustomize patching configuration
Type: submodule
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.kustomize.enable
Enable kustomize-based patching of helm output
Type: boolean
Default: false
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.kustomize.patches
Strategic merge patches to apply to helm output. Each patch is an attribute set that will be merged with matching resources.
Type: list of (attribute set)
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.kustomize.patchesJson6902
JSON Patch (RFC 6902) operations to apply to helm output.
Type: list of (attribute set)
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.kustomize.resources
Additional resources to include alongside helm output. Can be paths to YAML files or inline YAML strings.
Type: list of (absolute path or string)
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.namespace
Kubernetes namespace for the release
Type: string
Default: "default"
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.releaseName
Helm release name (defaults to attribute name)
Type: string
Default: "‹name›"
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.helmCharts.<name>.values
Helm values to pass to the chart
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources
Typed Kubernetes resources to include in this phase. Resources are validated against the generated K8s 1.31 API types and CRD types.
Type: attribute set of (open submodule of (attribute set))
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.apiVersion
Kubernetes API version (e.g., ‘v1’, ‘apps/v1’)
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.data
Data for ConfigMap/Secret resources
Type: null or (attribute set of string)
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.kind
Kubernetes resource kind (e.g., ‘Service’, ‘Deployment’)
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata
Resource metadata
Type: open submodule of (attribute set)
Default:
{
name = "‹name›";
}
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.annotations
Arbitrary non-identifying metadata attached to objects.
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.finalizers
List of finalizers that must be empty before the object is deleted.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.generateName
Optional prefix for generated names when name is not specified.
Type: null or string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.labels
Map of string keys and values for organizing and categorizing objects.
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.name
Resource name. Must be unique within a namespace.
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.namespace
Namespace for the resource. Null for cluster-scoped resources.
Type: null or string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences
List of objects depended by this object.
Type: list of (open submodule of (attribute set))
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.apiVersion
API version of the referent.
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.blockOwnerDeletion
If true, the owner cannot be deleted until this reference is removed.
Type: null or boolean
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.controller
If true, this reference points to the managing controller.
Type: null or boolean
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.kind
Kind of the referent.
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.name
Name of the referent.
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.metadata.ownerReferences.*.uid
UID of the referent.
Type: string
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.spec
Resource spec (structure depends on kind)
Type: null or (attribute set)
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.resources.<name>.stringData
String data for Secret resources
Type: null or (attribute set of string)
Declared in: modules/lab/cluster/phases
phases.<name>.bundles.<name>.yamls
Raw YAML manifests to include in this phase. Use this as an escape hatch when typed resources don’t fit. Can be inline strings or paths to YAML files.
Type: list of (string or absolute path)
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.crdNames
CRD names to wait for (used when waitForCRDs = true)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.dependsOn
Phases that must complete before this one
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/phases
phases.<name>.keepResources
Prevent deletion of resources in this phase
Type: boolean
Default: false
Declared in: modules/lab/cluster/phases
phases.<name>.order
Numeric ordering (lower = deployed earlier)
Type: signed integer
Declared in: modules/lab/cluster/phases
phases.<name>.pruneStrategy
Resource pruning behavior:
- default: normal prune
- never: never prune
- orphan: orphan on deletion
Type: one of "default", "never", "orphan"
Default: "default"
Declared in: modules/lab/cluster/phases
phases.<name>.timeout
Timeout for this phase’s deployment
Type: string
Default: "10m"
Declared in: modules/lab/cluster/phases
phases.<name>.waitForCRDs
Wait for CRDs to be established before deploying this phase
Type: boolean
Default: false
Declared in: modules/lab/cluster/phases
phases.<name>.waitForReady
Wait for all resources to become ready
Type: boolean
Default: true
Declared in: modules/lab/cluster/phases
provisioner.docker.clusterName
Docker cluster name
Type: string
Default: "catallaxy-‹name›"
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.colima.cpu
Number of CPUs for the VM
Type: signed integer
Default: 4
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.colima.disk
Disk size in GiB for the VM
Type: signed integer
Default: 60
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.colima.enable
Use Colima on macOS (auto-detected, ignored on Linux)
Type: boolean
Default: true
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.colima.memory
Memory in GiB for the VM
Type: signed integer
Default: 8
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.colima.profile
Colima profile name (isolates from other VMs)
Type: string
Default: "catallaxy"
Declared in: modules/lab/provisioners/docker.nix
provisioner.docker.waitTimeout
Timeout waiting for cluster to be ready
Type: string
Default: "10m"
Declared in: modules/lab/provisioners/docker.nix
provisioner.k3d.autoDeployManifests
Manifests to mount into k3s auto-deploy directory (/var/lib/rancher/k3s/server/manifests/). k3s applies these at boot. Used for pre-deploying CNI (Cilium) so nodes become Ready immediately.
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.autoDeployManifests.*.content
Nix store path to rendered manifest YAML
Type: absolute path
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.autoDeployManifests.*.name
Manifest filename (without .yaml)
Type: string
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.clusterName
k3d cluster name
Type: string
Default: "‹name›"
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.extraApiServerArgs
Extra kube-apiserver arguments passed to k3d via
–k3s-arg “–kube-apiserver-arg=
Type: list of string
Default: [ ]
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.extraVolumes
Extra volume mounts for k3d server nodes (e.g., CA certs)
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.extraVolumes.*.containerPath
Path inside k3d node
Type: string
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.extraVolumes.*.hostPath
Path on the Docker host
Type: string
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.image
Custom k3s image (null = k3d default)
Type: null or string
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.network
Docker network to create k3d cluster on (uses –network flag). When set, all clusters share this network for cross-cluster DNS.
Type: null or string
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.noFlannel
Disable default Flannel CNI (for Cilium)
Type: boolean
Default: true
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.noServiceLB
Disable default ServiceLB (Klipper)
Type: boolean
Default: true
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.noTraefik
Disable default Traefik ingress
Type: boolean
Default: true
Declared in: modules/lab/provisioners/k3d.nix
provisioner.k3d.ports
Port mappings for k3d (passed as -p flags).
Format: “
Type: list of string
Default: [ ]
Declared in: modules/lab/provisioners/k3d.nix
resources
This option has no description.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster
secrets.projections
Secret projections map lab-level managed secrets into Kubernetes Secrets. Each projection creates one K8s Secret with keys derived from a source managed secret, optionally transformed (base64, json-wrap).
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.keys
Key mappings from source managed secret to K8s Secret keys
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.keys.<name>.from
Source key name in the managed secret
Type: string
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.keys.<name>.jsonKey
JSON key name for json-wrap transform (defaults to the projection key name)
Type: null or string
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.keys.<name>.transform
Transform to apply when projecting:
- none: passthrough
- base64: base64-encode the value
- json-wrap: wrap as JSON object {“
”: “ ”}
Type: one of "none", "base64", "json-wrap"
Default: "none"
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.namespace
Kubernetes namespace for the projected Secret
Type: string
Default: "default"
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.phase
Deployment phase for injection
Type: string
Default: "secrets"
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.ref
Computed references for this projected secret
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/secrets
secrets.projections.<name>.source
Name of the lab-level managed secret (lab.secrets.managed.
Type: string
Declared in: modules/lab/cluster/components/secrets
secrets.sops.ageKeyFile
Path to age private key for decryption
Type: null or absolute path
Declared in: modules/lab/cluster/components/secrets/sops.nix
secrets.sops.defaultEncryptedSuffix
File suffix for encrypted files
Type: string
Default: ".enc.yaml"
Declared in: modules/lab/cluster/components/secrets/sops.nix
secrets.sops.enable
Whether to enable SOPS secrets management.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/secrets/sops.nix
storage.s3Buckets
This option has no description.
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster
CNI Options
Options for: cilium.
All options are under lab.clusters.<name>.components.
cilium.bandwidthManager.bbr
Enable BBR TCP congestion control
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bandwidthManager.enable
Enable bandwidth manager for rate limiting
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bgp.enable
Enable BGP control plane for advertising routes to external routers
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bgp.localASN
Local BGP Autonomous System Number for this cluster
Type: signed integer
Default: 65001
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bgp.peers
BGP peers to establish sessions with
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bgp.peers.*.address
BGP peer IP address
Type: string
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.bgp.peers.*.asn
BGP peer Autonomous System Number
Type: signed integer
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.chart
Cilium Helm chart derivation (default: cataCharts.cilium)
Type: package
Default: <derivation helm-chart-https-helm.cilium.io-cilium-1.17.2>
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.clusterMesh.clusterID
Unique cluster ID within the mesh (0-255)
Type: unsigned integer, meaning >=0
Default: 0
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.clusterMesh.clusterName
Cluster name for mesh identity (default: cluster.name)
Type: null or string
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.clusterMesh.enable
Enable multi-cluster networking via ClusterMesh
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.egressGateway.enable
Enable egress gateway for controlled outbound traffic
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.enable
Whether to enable Cilium CNI.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.encryption.enable
Enable transparent encryption of pod-to-pod traffic
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.encryption.nodeEncryption
Also encrypt node-to-node traffic
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.encryption.type
Encryption backend (WireGuard recommended)
Type: one of "wireguard", "ipsec"
Default: "wireguard"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.enable
Enable Kubernetes Gateway API support (replaces legacy Ingress)
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.domain
Base domain for wildcard cert (e.g. homelab.test → *.homelab.test)
Type: string
Default: ""
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.enable
Enable HTTPS listener on the default Gateway with cert-manager TLS
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.issuerRef
cert-manager issuer for the Gateway wildcard certificate
Type: submodule
Default:
{
kind = "ClusterIssuer";
name = "lab-ca";
}
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.issuerRef.kind
Issuer kind
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.issuerRef.name
cert-manager Issuer or ClusterIssuer name
Type: string
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.gatewayAPI.tls.passthrough.enable
Enable TLS passthrough listener on the Gateway (for backends that terminate TLS themselves)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.hubble.enable
Enable Hubble network observability
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.hubble.relay.enable
Enable Hubble Relay
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.hubble.ui.enable
Enable Hubble UI dashboard
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.ingressController.enable
Enable Cilium’s native ingress controller
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.ingressController.loadbalancerMode
LoadBalancer mode for ingress
Type: one of "shared", "dedicated"
Default: "shared"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.ipam.mode
IP Address Management mode
Type: one of "kubernetes", "cluster-pool"
Default: "kubernetes"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.k8sServiceHost
Kubernetes API server host. When null, auto-configured based on cluster provider:
- external (CAPI): uses Kubernetes service ClusterIP (10.96.0.1)
- docker (k3d): uses localhost
Type: null or string
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.k8sServicePort
Kubernetes API server port. When null, auto-configured based on cluster provider:
- external (CAPI): 443 (Kubernetes service port)
- docker (k3d): 6443
Type: null or string
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.kubeProxyReplacement
Replace kube-proxy with eBPF-based load balancing
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.l2.announcements
Enable L2 (ARP/NDP) announcements for service IPs
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.lbIPAM.enable
Enable LoadBalancer IP Address Management
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.lbIPAM.pools
IP address pools for LoadBalancer services
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.lbIPAM.pools.*.cidrs
CIDR ranges for IP allocation
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.lbIPAM.pools.*.name
Pool name
Type: string
Default: "default"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.networkPolicy.clusterNetworkPolicy
Enable CiliumClusterwideNetworkPolicy CRD
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.networkPolicy.enable
Enable Kubernetes NetworkPolicy enforcement
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.networkPolicy.hostFirewall
Enable host-level firewall enforcement
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.networkPolicy.policyAuditMode
Audit mode — log policy violations instead of enforcing
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.operator.replicas
Number of Cilium operator replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.phase
Deployment phase this component belongs to
Type: string
Default: "networking"
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.ref
Computed references for Cilium
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/cni/cilium.nix
cilium.version
Cilium version
Type: string
Default: "1.16.3"
Declared in: modules/lab/cluster/components/cni/cilium.nix
Gateway and DNS Options
Options for: gateway, external-dns.
All options are under lab.clusters.<name>.components.
external-dns.chart
ExternalDNS Helm chart derivation (default: cataCharts.external-dns)
Type: package
Default:
<derivation helm-chart-https-kubernetes-sigs.github.io-external-dns-external-dns-1.16.1>
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.defaultTargets
Override the target IP/hostname for all DNS records (e.g. [“127.0.0.1”] for local dev)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.domainFilters
Domains to manage (empty = all)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.enable
Whether to enable ExternalDNS.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.env
Extra environment variables (e.g. API tokens from secrets)
Type: list of (attribute set)
Default: [ ]
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.excludeDomains
Domains to exclude from management
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.extraArgs
Provider-specific extra arguments (e.g. { cloudflare-proxied = “true”; })
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.interval
Sync interval
Type: string
Default: "1m"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.logLevel
Log verbosity level
Type: one of "debug", "info", "warning", "error"
Default: "info"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.namespace
Namespace for ExternalDNS
Type: string
Default: "external-dns"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.policy
Record management policy (sync creates+updates+deletes)
Type: one of "sync", "upsert-only", "create-only"
Default: "sync"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.provider
DNS provider (cloudflare, route53, google, azure-dns, etc.)
Type: string
Default: "cloudflare"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.ref
Computed references for ExternalDNS
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.host
DNS server host for RFC2136 updates
Type: string
Default: ""
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.port
DNS server port
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 53
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.tsigAxfr
Enable AXFR (zone transfer) using TSIG. Not needed for basic operation.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.tsigKeyname
TSIG key name for authenticating DNS updates
Type: string
Default: "externaldns-key"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.tsigSecret
Base64-encoded TSIG secret
Type: string
Default: ""
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.tsigSecretAlg
TSIG secret algorithm
Type: one of "hmac-sha256", "hmac-sha512", "hmac-sha1"
Default: "hmac-sha256"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.rfc2136.zone
DNS zone to manage (e.g. ‘lab.test.’)
Type: string
Default: ""
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.serviceAccount.annotations
ServiceAccount annotations (for AWS IRSA, GCP Workload Identity, etc.)
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.sources
Kubernetes resource types to watch for DNS records
Type: list of string
Default:
[
"service"
"ingress"
"gateway-httproute"
"gateway-tlsroute"
]
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.triggerLoopOnEvent
React to resource events immediately rather than waiting for interval
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.txtOwnerId
TXT record ownership ID (defaults to cluster name)
Type: null or string
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.txtPrefix
Prefix for TXT ownership records
Type: string
Default: "externaldns-"
Declared in: modules/lab/cluster/components/external-dns.nix
external-dns.version
ExternalDNS Helm chart version
Type: string
Default: "1.15.0"
Declared in: modules/lab/cluster/components/external-dns.nix
gateway.chart
Traefik Helm chart derivation
Type: package
Default: <derivation helm-chart-https-traefik.github.io-charts-traefik-35.2.0>
Declared in: modules/lab/cluster/components/gateway.nix
gateway.className
GatewayClass name
Type: string
Default: "traefik"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.controller
Gateway controller to deploy:
- traefik: deploy Traefik v3 (default, good for k3d labs)
- external: skip controller deployment (use with Cilium or pre-installed controller)
Type: one of "traefik", "external"
Default: "traefik"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.controllerName
Gateway controller name for the GatewayClass
Type: string
Default: "traefik.io/gateway-controller"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.enable
Whether to enable Gateway API (standalone, CNI-agnostic).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/gateway.nix
gateway.gatewayName
Gateway resource name (components reference this via gateway.gatewayRef)
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.namespace
Namespace for the Gateway resource
Type: string
Default: "kube-system"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.domain
Base domain for wildcard cert (e.g. homelab.test)
Type: string
Default: ""
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.enable
Enable HTTPS listener with cert-manager TLS
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.issuerRef
This option has no description.
Type: submodule
Default:
{
kind = "ClusterIssuer";
name = "lab-ca";
}
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.issuerRef.kind
This option has no description.
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.issuerRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.passthrough.enable
Enable TLS passthrough listener (for backends that terminate TLS themselves)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/gateway.nix
gateway.tls.passthrough.port
Traefik entryPoint port for TLS passthrough (must differ from websecure port)
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 8444
Declared in: modules/lab/cluster/components/gateway.nix
PKI Options
Options for: cert-manager, trust-manager, pki-auth.
All options are under lab.clusters.<name>.components.
cert-manager.acme.dns01.cloudflare.apiToken
Cloudflare API token (if set, auto-creates the Secret)
Type: null or string
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.cloudflare.apiTokenSecretName
Name of Secret containing the Cloudflare API token (key: api-token)
Type: string
Default: "cloudflare-api-token"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.provider
Public DNS provider for ACME DNS01 challenges
Type: one of "none", "cloudflare", "route53"
Default: "none"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.route53.accessKeyID
AWS access key ID (for explicit credentials)
Type: string
Default: ""
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.route53.hostedZoneID
Route53 hosted zone ID
Type: string
Default: ""
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.route53.region
AWS region for Route53
Type: string
Default: "us-east-1"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.route53.secretAccessKey
AWS secret access key (if set, auto-creates the Secret)
Type: null or string
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.dns01.route53.secretAccessKeySecretName
Name of Secret containing AWS secret access key (key: secret-access-key)
Type: string
Default: "route53-credentials"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.email
Email for ACME registration
Type: string
Default: ""
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.enable
Create an ACME ClusterIssuer for Let’s Encrypt
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.issuerName
Name of the ACME ClusterIssuer
Type: string
Default: "letsencrypt"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.server
ACME server URL (use staging for testing)
Type: string
Default: "https://acme-v02.api.letsencrypt.org/directory"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.acme.solvers
Raw ACME solver config (overrides dns01 provider if set)
Type: list of (attribute set)
Default: [ ]
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.chart
cert-manager Helm chart derivation (default: cataCharts.cert-manager)
Type: package
Default: <derivation helm-chart-https-charts.jetstack.io-cert-manager-1.17.2>
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.enable
Whether to enable cert-manager.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.namespace
Namespace for cert-manager
Type: string
Default: "cert-manager"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.ref
Computed references for cert-manager
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.selfSignedCA.enable
Create a self-signed CA ClusterIssuer
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.selfSignedCA.issuerName
Name of the ClusterIssuer backed by the self-signed CA
Type: string
Default: "lab-ca"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
cert-manager.version
cert-manager version
Type: string
Default: "v1.16.1"
Declared in: modules/lab/cluster/components/pki/cert-manager.nix
pki-auth.ca.commonName
CA certificate Common Name
Type: string
Default: "catallaxy-‹name›-ca"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.ca.keyAlgorithm
CA private key algorithm
Type: one of "ecdsa-p256", "ecdsa-p384", "ed25519", "rsa-2048", "rsa-4096"
Default: "ecdsa-p256"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.ca.validity
CA certificate validity period
Type: string
Default: "10y"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.defaults.keyAlgorithm
Default key algorithm for client certificates
Type: one of "ecdsa-p256", "ecdsa-p384", "ed25519", "rsa-2048", "rsa-4096"
Default: "ecdsa-p256"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.defaults.renewBefore
Renew certificate this long before expiry
Type: string
Default: "30d"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.defaults.validity
Default client certificate validity
Type: string
Default: "1y"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.enable
Whether to enable PKI-based authentication (client certificates).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.namespace
Namespace for PKI auth RBAC resources
Type: string
Default: "pki-auth"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.rbac
Map of ClusterRoleBinding name → cert Organization → ClusterRole
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.rbac.<name>.clusterRole
ClusterRole to bind to this group
Type: string
Default: "cluster-admin"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.rbac.<name>.organization
Certificate Organization value (Kubernetes group name)
Type: string
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.ref
Computed references for PKI auth
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users
Users who receive client certificates for Kubernetes auth
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.commonName
Certificate Common Name — becomes the Kubernetes username. Typically an email address.
Type: string
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.keyAlgorithm
Override key algorithm for this user
Type: null or string
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.organizations
Certificate Organization fields — become Kubernetes groups. Bind these to ClusterRoles via the rbac option.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.validity
Override certificate validity for this user
Type: null or string
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.yubikey.pinPolicy
YubiKey PIN policy
Type: one of "once", "always", "never"
Default: "once"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.yubikey.serialNumber
YubiKey serial number for automatic provisioning.
When set, cata pki provision will target this specific device.
Type: null or string
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.yubikey.slot
PIV slot for the certificate (9a=authentication, 9c=signing)
Type: string
Default: "9a"
Declared in: modules/lab/cluster/auth/pki.nix
pki-auth.users.<name>.yubikey.touchPolicy
YubiKey touch policy (always=tap every use, cached=tap once per 15s)
Type: one of "always", "cached", "never"
Default: "always"
Declared in: modules/lab/cluster/auth/pki.nix
trust-manager.chart
This option has no description.
Type: package
Default: <derivation helm-chart-https-charts.jetstack.io-trust-manager-0.22.1>
Declared in: modules/lab/cluster/components/pki/trust-manager.nix
trust-manager.enable
Whether to enable trust-manager (CA bundle distribution).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/pki/trust-manager.nix
trust-manager.namespace
This option has no description.
Type: string
Default: "cert-manager"
Declared in: modules/lab/cluster/components/pki/trust-manager.nix
trust-manager.phase
This option has no description.
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/pki/trust-manager.nix
trust-manager.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/pki/trust-manager.nix
Observability Options
Options for: prometheus, grafana, loki, tempo, otel-collector.
All options are under lab.clusters.<name>.components.
grafana.adminCredentialsSecret
Existing secret with admin-user and admin-password keys
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.chart
Grafana Helm chart derivation (default: cataCharts.grafana)
Type: package
Default: <derivation helm-chart-https-grafana.github.io-helm-charts-grafana-10.5.15>
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.datasources.loki.url
Loki URL. Auto-configured from components.loki.ref when null and Loki is enabled.
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.datasources.prometheus.url
Prometheus URL. Auto-configured from components.prometheus.ref when null and Prometheus is enabled.
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.datasources.tempo.url
Tempo URL. Auto-configured from components.tempo.ref when null and Tempo is enabled.
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.domain
Domain for Grafana external access
Type: string
Default: "grafana.local"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.enable
Whether to enable Grafana.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.gateway.enable
Enable HTTPRoute for external access via Gateway API
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.gateway.gatewayNamespace
Namespace of the Gateway resource
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.gateway.gatewayRef
Name of the Gateway resource to attach to
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.namespace
Namespace for Grafana
Type: string
Default: "grafana"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.allowSignUp
Allow OIDC users to be created on first login
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.autoLogin
Automatically redirect to OIDC provider (skip login page)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.clientId
OAuth2 client ID
Type: string
Default: "grafana"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.clientSecretRef
Reference to Secret containing OIDC client secret
Type: null or (submodule)
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.clientSecretRef.key
Key within the secret
Type: string
Default: "client-secret"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.clientSecretRef.name
Secret containing OIDC client secret
Type: string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.enable
Whether to enable OIDC authentication via Kanidm.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.issuerUrl
OIDC issuer URL (e.g., from Kanidm ref)
Type: string
Default: ""
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.name
Display name for OIDC provider on login page
Type: string
Default: "Kanidm"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.roleAttributePath
JMESPath expression for mapping OIDC claims to Grafana roles
Type: string
Default:
"contains(groups[*], 'grafana-admins') && 'Admin' || contains(groups[*], 'grafana-editors') && 'Editor' || 'Viewer'"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.scopes
OIDC scopes to request
Type: list of string
Default:
[
"openid"
"email"
"profile"
"groups"
]
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaBundleConfigMap
ConfigMap containing CA bundle for OIDC provider (from trust-manager)
Type: null or (submodule)
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaBundleConfigMap.key
Key within the ConfigMap
Type: string
Default: "ca.crt"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaBundleConfigMap.name
ConfigMap containing CA bundle
Type: string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaCertSecretRef
Reference to Secret containing CA certificate for OIDC provider
Type: null or (submodule)
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaCertSecretRef.key
Key within the secret
Type: string
Default: "ca.crt"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsCaCertSecretRef.name
Secret containing CA certificate
Type: string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.oidc.tlsSkipVerify
Skip TLS certificate verification for OIDC provider
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.persistence.enable
Enable persistent storage for Grafana
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.persistence.size
PVC size for Grafana data
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.persistence.storageClass
Storage class for PVC
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.plugins
Grafana plugins to install (e.g., grafana-tempoexplore-app)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.ref
Computed references for Grafana
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.replicas
Number of Grafana replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.sidecar.dashboards.enable
Enable sidecar for auto-loading dashboards from ConfigMaps
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.sidecar.dashboards.searchNamespace
Namespace(s) to search for dashboard ConfigMaps. null = own namespace, ‘ALL’ = all namespaces.
Type: null or string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.tls.issuerRef
cert-manager issuer reference for Grafana TLS certificate
Type: null or (submodule)
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.tls.issuerRef.kind
Issuer kind
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.tls.issuerRef.name
Issuer or ClusterIssuer name
Type: string
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.tls.secretName
Name of the TLS Secret created by cert-manager
Type: string
Default: "grafana-tls"
Declared in: modules/lab/cluster/components/observability/grafana.nix
grafana.version
Grafana Helm chart version
Type: string
Default: "8.5.2"
Declared in: modules/lab/cluster/components/observability/grafana.nix
loki.chart
Loki Helm chart derivation (default: cataCharts.loki)
Type: package
Default: <derivation helm-chart-https-grafana.github.io-helm-charts-loki-6.30.1>
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.deploymentMode
Loki deployment topology
Type: one of "SingleBinary", "SimpleScalable", "Distributed"
Default: "SingleBinary"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.enable
Whether to enable Loki log aggregation.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.namespace
Namespace for Loki
Type: string
Default: "loki"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.ref
Computed references for Loki
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.replicas
Replicas (SingleBinary mode) or read/write replicas (SimpleScalable)
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.retention
Log retention period (default 31 days)
Type: string
Default: "744h"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.persistence.size
PVC size for local storage (filesystem mode)
Type: string
Default: "50Gi"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.persistence.storageClass
Storage class for PVCs
Type: null or string
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.s3.bucket
S3 bucket name
Type: string
Default: "loki-chunks"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.s3.endpoint
S3 endpoint URL (for S3-compatible storage). Use config.components.seaweedfs.ref.s3Endpoint for SeaweedFS.
Type: null or string
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.s3.region
S3 region
Type: string
Default: "us-east-1"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.s3.secretName
Secret with S3 credentials (access-key-id, secret-access-key keys)
Type: null or string
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.storage.type
Storage backend type
Type: one of "filesystem", "s3"
Default: "filesystem"
Declared in: modules/lab/cluster/components/observability/loki.nix
loki.version
Loki Helm chart version
Type: string
Default: "6.16.0"
Declared in: modules/lab/cluster/components/observability/loki.nix
otel-collector.agent.enable
Whether to enable OTEL agent (DaemonSet for log collection).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.excludeNamespaces
Namespaces to exclude from log collection (otel namespace auto-excluded)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.gateway.endpoint
Gateway OTLP endpoint (defaults to local gateway if not set)
Type: null or string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.namespaces
Namespaces to collect logs from (empty = all namespaces)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.resources.limits.cpu
This option has no description.
Type: string
Default: "200m"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.resources.limits.memory
This option has no description.
Type: string
Default: "256Mi"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.resources.requests.cpu
This option has no description.
Type: string
Default: "50m"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.agent.resources.requests.memory
This option has no description.
Type: string
Default: "128Mi"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.chart
OpenTelemetry Collector Helm chart derivation
Type: package
Default:
<derivation helm-chart-https-open-telemetry.github.io-opentelemetry-helm-charts-opentelemetry-collector-0.156.0>
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.enable
Whether to enable OpenTelemetry Collector.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.loki.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.loki.endpoint
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.otlp.endpoint
OTLP gRPC endpoint for traces/metrics/logs (e.g., host:4317)
Type: null or string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.otlphttp.endpoint
OTLP HTTP endpoint for traces/metrics/logs (e.g., http://host:4318)
Type: null or string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.prometheus.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.exporters.prometheus.endpoint
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.enable
Whether to enable OTEL gateway (Deployment for receiving/forwarding).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.domain
Domain for external access
Type: null or string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.enable
Whether to enable Expose gateway externally.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.tls.issuerRef
cert-manager issuer for the external gateway TLS certificate
Type: null or (submodule)
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.tls.issuerRef.kind
This option has no description.
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.tls.issuerRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.external.tls.secretName
This option has no description.
Type: string
Default: "otel-gateway-tls"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.replicas
Number of gateway replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.resources.limits.cpu
This option has no description.
Type: string
Default: "500m"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.resources.limits.memory
This option has no description.
Type: string
Default: "512Mi"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.resources.requests.cpu
This option has no description.
Type: string
Default: "100m"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.gateway.resources.requests.memory
This option has no description.
Type: string
Default: "256Mi"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.namespace
Namespace for OpenTelemetry Collector
Type: string
Default: "otel"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.ports.otlpGrpc
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 4317
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.ports.otlpHttp
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 4318
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.ports.prometheus
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 8889
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.ref
Computed references for the OpenTelemetry Collector
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.tls.caBundleConfigMap
ConfigMap containing the CA bundle for TLS verification on gateway exporters. When null, exporters use tls.insecure=true.
Type: null or string
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.tls.caBundleKey
Key within the CA bundle ConfigMap
Type: string
Default: "ca.crt"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
otel-collector.version
OpenTelemetry Collector Helm chart version
Type: string
Default: "0.96.0"
Declared in: modules/lab/cluster/components/observability/otel-collector.nix
prometheus.alertmanager.enable
Enable Alertmanager
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.chart
kube-prometheus-stack Helm chart derivation (default: cataCharts.prometheus)
Type: package
Default:
<derivation helm-chart-https-prometheus-community.github.io-helm-charts-kube-prometheus-stack-72.5.0>
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.defaultRules
Override default alert rule groups (e.g., { kubeEtcd = false; } to disable etcd rules)
Type: attribute set of boolean
Default: { }
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.enable
Whether to enable Prometheus (kube-prometheus-stack).
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.externalLabels
External labels added to all metrics (e.g., cluster name for multi-cluster)
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.gateway.domain
Domain for external remote-write ingestion
Type: string
Default: ""
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.gateway.enable
Expose Prometheus remote-write endpoint externally via Gateway API
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.gateway.gatewayNamespace
This option has no description.
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.gateway.gatewayRef
This option has no description.
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.grafana.enable
Enable the bundled Grafana (disable when using components.grafana)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.grafana.forceDeployDashboards
Deploy Kubernetes dashboard ConfigMaps even when bundled Grafana is disabled
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.kubeStateMetrics.enable
Enable kube-state-metrics
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.namespace
Namespace for Prometheus
Type: string
Default: "prometheus"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.nodeExporter.enable
Enable Node Exporter for host metrics
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.ref
Computed references for Prometheus
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.remoteWrite
Remote write endpoints for forwarding metrics
Type: list of (attribute set)
Default: [ ]
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.replicas
Number of Prometheus replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.retention
Metrics retention period
Type: string
Default: "15d"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.serviceMonitorSelector
Label selector for ServiceMonitors (empty = all)
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.storage.size
PVC size for Prometheus TSDB
Type: string
Default: "50Gi"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.storage.storageClass
Storage class for PVC
Type: null or string
Declared in: modules/lab/cluster/components/observability/prometheus.nix
prometheus.version
kube-prometheus-stack Helm chart version
Type: string
Default: "65.1.0"
Declared in: modules/lab/cluster/components/observability/prometheus.nix
tempo.chart
Tempo Helm chart derivation (default: cataCharts.tempo)
Type: package
Default: <derivation helm-chart-https-grafana.github.io-helm-charts-tempo-1.21.0>
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.deploymentMode
Tempo deployment topology
Type: one of "monolithic", "distributed"
Default: "monolithic"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.enable
Whether to enable Tempo distributed tracing.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.namespace
Namespace for Tempo
Type: string
Default: "tempo"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.receivers.otlp.grpc
Enable OTLP gRPC receiver
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.receivers.otlp.http
Enable OTLP HTTP receiver
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.ref
Computed references for Tempo
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.retention
Trace retention period (default 7 days)
Type: string
Default: "168h"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.persistence.size
PVC size for trace storage (filesystem mode)
Type: string
Default: "20Gi"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.persistence.storageClass
Storage class for PVCs
Type: null or string
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.s3.bucket
S3 bucket name
Type: string
Default: "tempo-traces"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.s3.endpoint
S3 endpoint URL (for S3-compatible storage). Use config.components.seaweedfs.ref.s3Endpoint for SeaweedFS.
Type: null or string
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.s3.region
S3 region
Type: string
Default: "us-east-1"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.s3.secretName
Secret with S3 credentials
Type: null or string
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.storage.type
Trace storage backend
Type: one of "filesystem", "s3"
Default: "filesystem"
Declared in: modules/lab/cluster/components/observability/tempo.nix
tempo.version
Tempo Helm chart version
Type: string
Default: "1.10.3"
Declared in: modules/lab/cluster/components/observability/tempo.nix
Databases Options
Options for: cnpg, redis-operator.
All options are under lab.clusters.<name>.components.
cnpg.chart
Custom chart derivation. When null, uses nixhelm default.
Type: package
Default:
<derivation helm-chart-https-cloudnative-pg.github.io-charts-cloudnative-pg-0.23.0>
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters
Declarative PostgreSQL clusters managed by CNPG
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.backup.enable
Enable automated backups
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.backup.retentionPolicy
Backup retention policy
Type: string
Default: "30d"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.backup.schedule
Cron schedule for backups
Type: string
Default: "0 0 * * *"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.createNamespace
Whether to create the namespace (set to false if another app manages it)
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases
Databases to create in this cluster
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases.<name>.extensions
PostgreSQL extensions to enable for this database
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases.<name>.owner
Database owner username
Type: string
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases.<name>.userPasswordSecretRef
Reference to Secret containing the database user’s password
Type: null or (submodule)
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases.<name>.userPasswordSecretRef.key
Key within the secret
Type: string
Default: "password"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.databases.<name>.userPasswordSecretRef.name
Secret containing user password
Type: string
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.enable
Enable this PostgreSQL cluster
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.instances
Number of PostgreSQL instances (replicas)
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.monitoring.enable
Enable Prometheus metrics
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.namespace
Namespace for this cluster
Type: string
Default: "databases"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.postgresql.parameters
PostgreSQL configuration parameters
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.postgresql.version
PostgreSQL major version
Type: string
Default: "16"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.ref
Computed references for this cluster
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.storage.size
PVC size for each instance
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.storage.storageClass
Storage class for PVCs. Null uses the cluster default.
Type: null or string
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.superuserPasswordSecretRef
Reference to Secret containing superuser password for bootstrap
Type: null or (submodule)
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.superuserPasswordSecretRef.key
Key within the secret
Type: string
Default: "password"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.clusters.<name>.superuserPasswordSecretRef.name
Secret name containing superuser password
Type: string
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.enable
Whether to enable CloudNativePG operator.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.namespace
Namespace for the CloudNativePG operator
Type: string
Default: "cnpg-system"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.ref
Computed references for CNPG
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/databases/cnpg.nix
cnpg.version
CloudNativePG operator chart version
Type: string
Default: "0.22.0"
Declared in: modules/lab/cluster/components/databases/cnpg.nix
redis-operator.chart
Custom chart derivation. When null, uses nixhelm default.
Type: package
Default:
<derivation helm-chart-https-ot-container-kit.github.io-helm-charts-redis-operator-0.18.2>
Declared in: modules/lab/cluster/components/redis-operator.nix
redis-operator.enable
Whether to enable Redis operator.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/redis-operator.nix
redis-operator.namespace
Namespace for the Redis operator
Type: string
Default: "redis-operator"
Declared in: modules/lab/cluster/components/redis-operator.nix
redis-operator.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/redis-operator.nix
redis-operator.ref
Computed references for Redis operator
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/redis-operator.nix
redis-operator.version
Redis operator chart version
Type: string
Default: "0.18.0"
Declared in: modules/lab/cluster/components/redis-operator.nix
Filesystems Options
Options for: openebs, seaweedfs.
All options are under lab.clusters.<name>.components.
openebs.chart
Custom chart derivation. When null, uses nixhelm default.
Type: package
Default:
<derivation helm-chart-https-charts.containeroo.ch-local-path-provisioner-0.0.30>
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.enable
Whether to enable OpenEBS storage operator.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.engine
Storage engine:
- hostpath: local path provisioner (dev/single-node)
- lvm: LVM-based local storage
- zfs: ZFS-based local storage
- mayastor: replicated NVMe-oF storage (production HA)
Type: one of "hostpath", "lvm", "zfs", "mayastor"
Default: "hostpath"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.mayastor.cpuCount
CPU cores allocated to each Mayastor instance
Type: positive integer, meaning >0
Default: 2
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.mayastor.replicas
Number of Mayastor IO engine replicas
Type: positive integer, meaning >0
Default: 3
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.namespace
Namespace for OpenEBS
Type: string
Default: "openebs"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.ref
Computed references for OpenEBS
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.storageClasses
StorageClass definitions to create
Type: attribute set of (submodule)
Default:
{
openebs-default = {
isDefault = true;
};
}
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.storageClasses.<name>.isDefault
Set as the cluster’s default StorageClass
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.storageClasses.<name>.reclaimPolicy
PV reclaim policy
Type: one of "Delete", "Retain"
Default: "Delete"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.storageClasses.<name>.volumeBindingMode
Volume binding mode
Type: one of "WaitForFirstConsumer", "Immediate"
Default: "WaitForFirstConsumer"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
openebs.version
OpenEBS version
Type: string
Default: "4.1.1"
Declared in: modules/lab/cluster/components/filesystems/openebs.nix
seaweedfs.chart
Custom chart derivation. When null, uses nixhelm default.
Type: package
Default: <derivation helm-chart-https-seaweedfs.github.io-seaweedfs-helm-seaweedfs-4.0.0>
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.enable
Whether to enable SeaweedFS distributed storage.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.filer.replicas
Number of filer replicas (2+ for production)
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.filer.s3.enable
Enable S3 API gateway on the filer
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.filer.storage
Storage size for filer metadata
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.master.replicas
Number of master server replicas (3 for production)
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.master.storage
Storage size for master metadata
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.namespace
Namespace for SeaweedFS
Type: string
Default: "seaweedfs"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.ref
Computed references for SeaweedFS
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.s3.enable
Enable S3 API
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.s3.port
S3 API port
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 8333
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.version
SeaweedFS version
Type: string
Default: "3.71"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.volume.replicas
Number of volume server replicas (3+ for production)
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.volume.storage
Storage size per volume server
Type: string
Default: "50Gi"
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
seaweedfs.volume.storageClass
StorageClass for volume server PVCs (null = cluster default)
Type: null or string
Declared in: modules/lab/cluster/components/filesystems/seaweedfs.nix
Secrets Options
Options for: external-secrets, sops.
All options are under lab.clusters.<name>.components.
external-secrets.chart
External Secrets Helm chart derivation (default: cataCharts.external-secrets)
Type: package
Default: <derivation helm-chart-https-charts.external-secrets.io-external-secrets-0.15.0>
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
external-secrets.enable
Whether to enable External Secrets Operator.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
external-secrets.namespace
Namespace for External Secrets Operator
Type: string
Default: "external-secrets"
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
external-secrets.phase
Deployment phase this component belongs to
Type: string
Default: "secrets"
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
external-secrets.ref
Computed references for External Secrets Operator
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
external-secrets.version
External Secrets Operator version
Type: string
Default: "0.10.0"
Declared in: modules/lab/cluster/components/secrets/external-secrets.nix
Identity Options
Options for: kanidm, kaniop, oidc.
All options are under lab.clusters.<name>.components.
kanidm.backup.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.backup.schedule
This option has no description.
Type: string
Default: "0 2 * * *"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.chart
This option has no description.
Type: package
Default: <derivation helm-chart-https-datosh.github.io-kanidm-kanidm-0.2.1>
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.domain
This option has no description.
Type: string
Default: "idm.example.com"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.enable
Whether to enable Kanidm identity management.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.gateway.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.gateway.gatewayNamespace
This option has no description.
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.gateway.gatewayRef
This option has no description.
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.gateway.mode
TLS mode: ‘terminate’ uses HTTPRoute + BackendTLSPolicy, ‘passthrough’ uses TLSRoute (raw TLS to backend)
Type: one of "terminate", "passthrough"
Default: "terminate"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.accountPolicy
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.accountPolicy.authSessionExpiry
This option has no description.
Type: signed integer
Default: 86400
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.accountPolicy.credentialTypeMinimum
This option has no description.
Type: one of "any", "mfa", "passkey", "attested_passkey"
Default: "any"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.accountPolicy.passwordMinimumLength
This option has no description.
Type: signed integer
Default: 12
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.accountPolicy.privilegeExpiry
This option has no description.
Type: signed integer
Default: 900
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.entryManagedBy
Group or account that manages this group
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.mail
Group email addresses
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.members
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.posixAttributes
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.groups.<name>.posixAttributes.gidnumber
This option has no description.
Type: null or signed integer
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.instanceName
This option has no description.
Type: string
Default: "kanidm"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.namespace
This option has no description.
Type: string
Default: "kanidm"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2ClientNamespaceSelector
Namespace selector for KanidmOAuth2Client discovery. {} = all namespaces.
Type: null or (attribute set)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.allowInsecureClientDisablePkce
Disable PKCE enforcement for confidential clients whose OIDC library doesn’t support it (e.g. Dex)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.allowLocalhostRedirect
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap
Custom claim mappings from group membership
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap.*.joinStrategy
This option has no description.
Type: one of "csv", "ssv", "array"
Default: "array"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap.*.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap.*.valuesMap
This option has no description.
Type: list of (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap.*.valuesMap.*.group
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.claimMap.*.valuesMap.*.values
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.disableConsentPrompt
Skip user consent screen (for admin-managed apps)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.displayName
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.namespace
Namespace for this OAuth2Client CR and its generated secret. null = kanidm namespace.
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.origin
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.preferShortUsername
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.public
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.redirectUrls
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.scopeMap
This option has no description.
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.scopeMap.*.group
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.scopeMap.*.scopes
This option has no description.
Type: list of string
Default:
[
"openid"
"email"
"groups"
]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.secretTemplate
Extra labels for the kaniop-generated credential secret
Type: null or (attribute set of string)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.strictRedirectUrl
Require exact redirect URL matching
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.supScopeMap
Supplementary scopes (optional claims not used for authz)
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.supScopeMap.*.group
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.oauth2Clients.<name>.supScopeMap.*.scopes
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.origin
This option has no description.
Type: string
Default: "https://idm.example.com"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.phase
This option has no description.
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.replicas
This option has no description.
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts
Service accounts (bots/daemons) with API tokens
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.accountExpire
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.accountValidFrom
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.apiTokens
This option has no description.
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.apiTokens.*.expiry
RFC3339 expiry (e.g. 2026-12-31T00:00:00Z)
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.apiTokens.*.label
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.apiTokens.*.purpose
This option has no description.
Type: one of "readonly", "readwrite"
Default: "readonly"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.apiTokens.*.secretName
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.displayName
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.entryManagedBy
Group or account that manages this service account
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.serviceAccounts.<name>.mail
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.storage.size
This option has no description.
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.storage.storageClass
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.tls.issuerRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.tls.issuerRef.kind
This option has no description.
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.tls.issuerRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.tls.secretName
This option has no description.
Type: string
Default: "kanidm-tls"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.accountExpire
ISO 8601 timestamp — account expires after this time
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.accountValidFrom
ISO 8601 timestamp — account is invalid before this time
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.credential
This option has no description.
Type: one of "token", "password", "passkey"
Default: "token"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.credentialsTokenTtl
This option has no description.
Type: signed integer
Default: 3600
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.displayName
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.email
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.groups
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.legalName
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.passwordSecretRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.passwordSecretRef.key
This option has no description.
Type: string
Default: "password"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.passwordSecretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.posixAttributes
POSIX/Unix attributes for SSH and Linux integration
Type: null or (submodule)
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.posixAttributes.gidnumber
Unix UID/GID (auto-generated if null)
Type: null or signed integer
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.users.<name>.posixAttributes.loginshell
This option has no description.
Type: string
Default: "/bin/bash"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kanidm.version
This option has no description.
Type: string
Default: "1.4.2"
Declared in: modules/lab/cluster/components/idm/kanidm.nix
kaniop.chart
Custom chart derivation. When null, uses OCI chart.
Type: package
Default: <derivation helm-chart-oci-ghcr.io-pando85-helm-charts-kaniop-0.6.1>
Declared in: modules/lab/cluster/components/idm/kaniop.nix
kaniop.enable
Whether to enable Kaniop operator for declarative Kanidm management.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/idm/kaniop.nix
kaniop.namespace
Namespace for Kaniop operator (same as Kanidm)
Type: string
Default: "kanidm"
Declared in: modules/lab/cluster/components/idm/kaniop.nix
kaniop.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/idm/kaniop.nix
kaniop.ref
Computed references for Kaniop
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/idm/kaniop.nix
kaniop.version
Kaniop operator version
Type: string
Default: "0.6.1"
Declared in: modules/lab/cluster/components/idm/kaniop.nix
oidc.caSecretRef
Reference to Secret containing the OIDC issuer CA certificate
Type: null or (submodule)
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.caSecretRef.key
Key within the secret
Type: string
Default: "ca.crt"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.caSecretRef.name
Secret name containing CA cert
Type: string
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.caSecretRef.namespace
Secret namespace
Type: string
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.clientId
OIDC client ID registered in the identity provider
Type: string
Default: "kubernetes"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.enable
Whether to enable OIDC authentication for Kubernetes API server.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.groupsClaim
JWT claim containing group memberships
Type: string
Default: "groups"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.groupsPrefix
Prefix added to OIDC groups to avoid collisions
Type: string
Default: "oidc:"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.issuerUrl
OIDC issuer URL for the Kubernetes API server.
Use config.components.kanidm.ref.oauth2Clients.
Type: string
Default: ""
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.namespace
Namespace for OIDC RBAC resources
Type: string
Default: "kube-system"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.rbac
Map of ClusterRoleBinding name to OIDC group + ClusterRole
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.rbac.<name>.clusterRole
ClusterRole to bind to the OIDC group
Type: string
Default: "cluster-admin"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.rbac.<name>.group
OIDC group name (groupsPrefix will be prepended)
Type: string
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.ref
Computed references for OIDC
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.usernameClaim
JWT claim to use as the Kubernetes username
Type: string
Default: "email"
Declared in: modules/lab/cluster/auth/oidc.nix
oidc.usernamePrefix
Prefix added to OIDC usernames to avoid collisions
Type: string
Default: "oidc:"
Declared in: modules/lab/cluster/auth/oidc.nix
GitOps Options
Options for: argocd.
All options are under lab.clusters.<name>.components.
argocd.chart
ArgoCD Helm chart derivation (default: cataCharts.argocd)
Type: package
Default: <derivation helm-chart-https-argoproj.github.io-argo-helm-argo-cd-8.0.2>
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.domain
Domain for ArgoCD external access
Type: string
Default: ""
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.enable
Whether to enable ArgoCD.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.gateway.enable
Enable HTTPRoute for external access via Gateway API
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.gateway.gatewayNamespace
Namespace of the Gateway resource
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.gateway.gatewayRef
Name of the Gateway resource to attach to
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.ha
Install HA version of ArgoCD
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.namespace
Namespace for ArgoCD
Type: string
Default: "argocd"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.caBundleConfigMap
ConfigMap containing CA bundle for OIDC issuer TLS verification (from trust-manager)
Type: null or string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.caBundleKey
Key within the CA bundle ConfigMap
Type: string
Default: "ca.crt"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.clientId
OAuth2 client ID
Type: string
Default: "argocd"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.clientSecretRef
Reference to Secret containing OIDC client secret
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.clientSecretRef.key
Key within the secret
Type: string
Default: "client-secret"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.clientSecretRef.name
Secret containing OIDC client secret
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.enable
Whether to enable OIDC authentication.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.issuerUrl
OIDC issuer URL
Type: string
Default: ""
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.oidc.name
Display name for OIDC provider
Type: string
Default: "Kanidm"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.phase
Deployment phase this component belongs to
Type: string
Default: "gitops"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.ref
Computed references for ArgoCD
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories
Repository credentials for ArgoCD
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.enableLfs
Enable Git LFS for this repository
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.insecure
Skip TLS certificate verification
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.passwordSecretRef
Reference to Secret containing repository password or access token
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.passwordSecretRef.key
Key within the secret
Type: string
Default: "password"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.passwordSecretRef.name
Secret containing password/token
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.project
ArgoCD project to associate this repository with
Type: string
Default: "default"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.sshPrivateKeySecretRef
Reference to Secret containing SSH private key for repository access
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.sshPrivateKeySecretRef.key
Key within the secret
Type: string
Default: "ssh-privatekey"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.sshPrivateKeySecretRef.name
Secret containing SSH private key
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.tlsClientCertSecretRef
Reference to Secret containing TLS client certificate for repository access
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.tlsClientCertSecretRef.certKey
Key for the certificate
Type: string
Default: "tls.crt"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.tlsClientCertSecretRef.keyKey
Key for the private key
Type: string
Default: "tls.key"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.tlsClientCertSecretRef.name
Secret containing TLS client certificate
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.type
Repository type
Type: one of "git", "helm"
Default: "git"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.url
Repository URL
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.usernameSecretRef
Reference to Secret containing repository username
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.usernameSecretRef.key
Key within the secret
Type: string
Default: "username"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.repositories.<name>.usernameSecretRef.name
Secret containing username
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.tls.issuerRef
cert-manager issuer reference for ArgoCD TLS certificate
Type: null or (submodule)
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.tls.issuerRef.kind
Issuer kind
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.tls.issuerRef.name
Issuer or ClusterIssuer name
Type: string
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.tls.secretName
Name of the TLS Secret created by cert-manager
Type: string
Default: "argocd-tls"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
argocd.version
ArgoCD version
Type: string
Default: "v2.13.0"
Declared in: modules/lab/cluster/components/gitops/argocd.nix
Source Control Options
Options for: forgejo.
All options are under lab.clusters.<name>.components.
forgejo.admin.existingSecret
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.chart
Custom chart derivation
Type: package
Default: <derivation helm-chart-oci-codeberg.org-forgejo-contrib-forgejo-5.1.0>
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.host
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.name
This option has no description.
Type: string
Default: "forgejo"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.port
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 5432
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.secretRef
This option has no description.
Type: submodule
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.secretRef.key
This option has no description.
Type: string
Default: "password"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.secretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.ssl
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.database.user
This option has no description.
Type: string
Default: "forgejo"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.domain
Domain for Forgejo external access
Type: string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.enable
Whether to enable Forgejo git forge.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.gateway.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.gateway.gatewayNamespace
This option has no description.
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.gateway.gatewayRef
This option has no description.
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.namespace
Namespace for Forgejo
Type: string
Default: "forgejo"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.adminGroup
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.autoDiscoverUrl
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.clientId
This option has no description.
Type: string
Default: "forgejo"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.clientSecretRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.clientSecretRef.key
This option has no description.
Type: string
Default: "client-secret"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.clientSecretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.enable
Whether to enable OIDC authentication via Kanidm.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.groupsClaim
This option has no description.
Type: string
Default: "groups"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.issuerUrl
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.providerName
This option has no description.
Type: string
Default: "Kanidm"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.scopes
This option has no description.
Type: list of string
Default:
[
"openid"
"email"
"profile"
"groups"
]
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.oidc.usernameClaim
This option has no description.
Type: string
Default: "preferred_username"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.phase
Deployment phase this component belongs to
Type: string
Default: "apps"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.replicas
This option has no description.
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.server.httpPort
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 3000
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.server.lfsEnabled
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.server.sshPort
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 22
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.storage.size
This option has no description.
Type: string
Default: "10Gi"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.storage.storageClass
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.tls.issuerRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.tls.issuerRef.kind
This option has no description.
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.tls.issuerRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.tls.secretName
This option has no description.
Type: string
Default: "forgejo-tls"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
forgejo.version
Forgejo version
Type: string
Default: "11.0.14"
Declared in: modules/lab/cluster/components/source-control/forgejo.nix
Provisioning Options
Options for: cluster-api, crossplane.
All options are under lab.clusters.<name>.components.
cluster-api.bootstrapProviders
This option has no description.
Type: list of (one of "kubeadm", "talos")
Default:
[
"talos"
]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.chart
This option has no description.
Type: package
Default:
<derivation helm-chart-https-kubernetes-sigs.github.io-cluster-api-operator-cluster-api-operator-0.27.0>
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.apiServerExtraArgs
This option has no description.
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.aws.controlPlaneInstanceType
This option has no description.
Type: string
Default: "t3.large"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.aws.region
This option has no description.
Type: string
Default: "us-east-1"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.aws.sshKeyName
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.aws.workerInstanceType
This option has no description.
Type: string
Default: "t3.large"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.certSANs
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.clientCaCert
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.digitalocean.controlPlaneSize
This option has no description.
Type: string
Default: "s-2vcpu-4gb"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.digitalocean.image
This option has no description.
Type: string
Default: "ubuntu-24-04-x64"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.digitalocean.region
This option has no description.
Type: string
Default: "nyc1"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.digitalocean.sshKeys
SSH key fingerprints or IDs
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.digitalocean.workerSize
This option has no description.
Type: string
Default: "s-2vcpu-4gb"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.docker.loadBalancerImage
This option has no description.
Type: string
Default: "kindest/haproxy:v20230606-42a2262b"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.controlPlaneType
This option has no description.
Type: string
Default: "cpx31"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.network.cidr
This option has no description.
Type: string
Default: "10.0.0.0/8"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.network.enabled
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.placementGroup
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.region
This option has no description.
Type: string
Default: "fsn1"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.sshKeyName
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.hetzner.workerType
This option has no description.
Type: string
Default: "cpx31"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.infrastructureProvider
This option has no description.
Type: one of "docker", "digitalocean", "hetzner", "aws", "gcp", "azure", "vsphere"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.controlPlane.machineType
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.controlPlane.replicas
This option has no description.
Type: signed integer
Default: 3
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.version
This option has no description.
Type: string
Default: "v1.31.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers
This option has no description.
Type: list of (submodule)
Default:
[
{
name = "default";
replicas = 3;
}
]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.labels
This option has no description.
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.machineType
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.name
Name of the worker pool
Type: string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.replicas
This option has no description.
Type: signed integer
Default: 3
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.taints
This option has no description.
Type: list of (submodule)
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.taints.*.effect
This option has no description.
Type: one of "NoSchedule", "PreferNoSchedule", "NoExecute"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.taints.*.key
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.kubernetes.workers.*.taints.*.value
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.network.podCIDR
This option has no description.
Type: string
Default: "10.244.0.0/16"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.network.serviceCIDR
This option has no description.
Type: string
Default: "10.96.0.0/12"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.registryMirror.enable
Configure containerd registry mirrors on CAPI cluster nodes
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.registryMirror.endpoint
Registry mirror endpoint (e.g., http://docker-host:port)
Type: string
Default: "http://172.17.0.1:5050"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.registryMirror.registries
Upstream registries to mirror through the cache
Type: list of string
Default:
[
"docker.io"
"ghcr.io"
"quay.io"
"registry.k8s.io"
]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.talos.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.clusters.<name>.talos.version
This option has no description.
Type: string
Default: "v1.8.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.controlPlaneProviders
This option has no description.
Type: list of (one of "kubeadm", "talos")
Default:
[
"talos"
]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.enable
Whether to enable Cluster API.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.infrastructureProviders
This option has no description.
Type: list of (one of "docker", "digitalocean", "aws", "gcp", "azure", "hetzner", "vsphere")
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.isManagementCluster
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.namespace
This option has no description.
Type: string
Default: "capi-system"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.phase
This option has no description.
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.aws
This option has no description.
Type: string
Default: "2.7.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.core
This option has no description.
Type: string
Default: "1.13.2"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.digitalocean
This option has no description.
Type: string
Default: "1.6.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.docker
This option has no description.
Type: string
Default: "1.9.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.hetzner
This option has no description.
Type: string
Default: "1.0.0-beta.40"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.talosBootstrap
This option has no description.
Type: string
Default: "0.6.7"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.providerVersions.talosControlPlane
This option has no description.
Type: string
Default: "0.5.13"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
cluster-api.version
This option has no description.
Type: string
Default: "1.9.0"
Declared in: modules/lab/cluster/components/provisioning/cluster-api.nix
crossplane.chart
This option has no description.
Type: package
Default: <derivation helm-chart-https-charts.crossplane.io-stable-crossplane-1.18.2>
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.apiToken
Cloudflare API token (for dev/lab use). For production, use SOPS-encrypted secrets.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.credentialSecretRef
This option has no description.
Type: null or (submodule)
Default:
{
key = "credentials";
name = "cf-credentials";
namespace = "crossplane-system";
}
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.credentialSecretRef.key
This option has no description.
Type: string
Default: "credentials"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.credentialSecretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.credentialSecretRef.namespace
This option has no description.
Type: string
Default: "crossplane-system"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.proxied
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.ttl
This option has no description.
Type: signed integer
Default: 300
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.type
This option has no description.
Type: one of "A", "AAAA", "CNAME", "MX", "TXT", "SRV", "NS"
Default: "A"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.value
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.records.<name>.zoneRef
Name of the Crossplane Zone resource to reference
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.tunnels
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.tunnels.<name>.accountId
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.tunnels.<name>.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.tunnels.<name>.secret
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.zones
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.zones.<name>.accountId
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.zones.<name>.domain
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.cloudflare.zones.<name>.plan
This option has no description.
Type: string
Default: "free"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.apiToken
DO API token (for dev/lab use). For production, use SOPS-encrypted secrets.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.credentialSecretRef
This option has no description.
Type: null or (submodule)
Default:
{
key = "credentials";
name = "do-credentials";
namespace = "crossplane-system";
}
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.credentialSecretRef.key
This option has no description.
Type: string
Default: "credentials"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.credentialSecretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.credentialSecretRef.namespace
This option has no description.
Type: string
Default: "crossplane-system"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.image
This option has no description.
Type: string
Default: "ubuntu-24-04-x64"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.region
This option has no description.
Type: string
Default: "nyc1"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.size
This option has no description.
Type: string
Default: "s-2vcpu-4gb"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.sshKeys
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.userData
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.droplets.<name>.vpcUuid
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters
DigitalOcean managed Kubernetes (DOKS) clusters
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.autoUpgrade
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.ha
Enable HA control plane
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.autoScale
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.maxNodes
This option has no description.
Type: null or signed integer
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.minNodes
This option has no description.
Type: null or signed integer
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.name
This option has no description.
Type: string
Default: "default"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.nodeCount
This option has no description.
Type: signed integer
Default: 2
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.nodePool.size
This option has no description.
Type: string
Default: "s-2vcpu-4gb"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.region
This option has no description.
Type: string
Default: "nyc1"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.surgeUpgrade
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.kubernetesClusters.<name>.version
Kubernetes version slug (e.g., ‘1.36.0-do.0’). Find valid versions with doctl kubernetes options versions.
Type: string
Default: "1.36.0-do.0"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.loadBalancers
This option has no description.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.loadBalancers.<name>.dropletTag
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.loadBalancers.<name>.forwardingRules
This option has no description.
Type: list of (attribute set)
Default:
[
{
entryPort = 80;
entryProtocol = "http";
targetPort = 80;
targetProtocol = "http";
}
]
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.digitalocean.loadBalancers.<name>.region
This option has no description.
Type: string
Default: "nyc1"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.enable
Whether to enable Crossplane infrastructure provisioning.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.namespace
This option has no description.
Type: string
Default: "crossplane-system"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.phase
This option has no description.
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.providerVersions.cloudflare
This option has no description.
Type: string
Default: "0.2.5"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.providerVersions.digitalocean
This option has no description.
Type: string
Default: "0.3.2"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.providerVersions.helm
This option has no description.
Type: string
Default: "1.2.0"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.providerVersions.kubernetes
This option has no description.
Type: string
Default: "1.2.1"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.providers
Crossplane providers to install
Type: list of (one of "digitalocean", "cloudflare", "kubernetes", "helm")
Default: [ ]
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
crossplane.version
This option has no description.
Type: string
Default: "1.18.2"
Declared in: modules/lab/cluster/components/provisioning/crossplane.nix
Other Components Options
Options for: velero, netbird, zot, custom.
All options are under lab.clusters.<name>.components.
custom.apps
Custom applications to deploy. Each app gets its own bundle within the specified phase. Supports Helm charts, typed resources, raw YAML, and optional Gateway API routing.
Type: attribute set of (submodule)
Default: { }
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.createNamespace
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.domain
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.gatewayNamespace
This option has no description.
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.gatewayRef
This option has no description.
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.mode
This option has no description.
Type: one of "terminate", "passthrough"
Default: "terminate"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.serviceName
Backend service name for the HTTPRoute/TLSRoute
Type: string
Default: "‹name›"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.gateway.servicePort
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 80
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.helmCharts
Helm charts to deploy (same shape as phase bundle helmCharts)
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.namespace
Kubernetes namespace (defaults to app name)
Type: string
Default: "‹name›"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.phase
Deployment phase (apps, workloads, infrastructure, etc.)
Type: string
Default: "apps"
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.resources
Typed Kubernetes resources
Type: attribute set of (attribute set)
Default: { }
Declared in: modules/lab/cluster/components/custom.nix
custom.apps.<name>.yamls
Raw YAML manifests
Type: list of (string or absolute path)
Default: [ ]
Declared in: modules/lab/cluster/components/custom.nix
netbird.chart
Custom chart derivation. When null, uses nixhelm default.
Type: package
Default: <derivation helm-chart-https-charts.jaconi.io-netbird-0.15.0>
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.domain
Domain name for the Netbird management server
Type: string
Default: "vpn.example.com"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.enable
Whether to enable Netbird mesh VPN.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.idp.clientID
OIDC client ID
Type: string
Default: "netbird"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.idp.clientSecretRef
Reference to the OIDC client secret.
Use config.secrets.managed.
Type: null or (attribute set)
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.idp.issuer
OIDC issuer URL. Use config.components.kanidm.ref.oidcIssuer for type-safe Kanidm integration.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.management.replicas
Number of management server replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.management.storage.size
PVC size for management server data
Type: string
Default: "5Gi"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.management.storage.storageClass
StorageClass (null = cluster default)
Type: null or string
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.namespace
Namespace for Netbird
Type: string
Default: "netbird"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.phase
Deployment phase this component belongs to
Type: string
Default: "infrastructure"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.ref
Computed references for Netbird
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.signal.replicas
Number of signal server replicas
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.turn.domain
Domain for the TURN server
Type: string
Default: "turn.example.com"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.turn.enable
Enable TURN relay for NAT traversal
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/vpn/netbird.nix
netbird.version
Netbird version
Type: string
Default: "0.31.0"
Declared in: modules/lab/cluster/components/vpn/netbird.nix
velero.backupStorageLocation.bucket
Bucket/container name for backups
Type: string
Default: "velero-backups"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.credentialsSecret
Name of the secret containing storage credentials
Type: string
Default: "velero-credentials"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.prefix
Prefix within the bucket for backups
Type: string
Default: ""
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.provider
Backup storage provider
Type: one of "aws", "gcp", "azure", "seaweedfs", "filesystem"
Default: "seaweedfs"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.s3.endpoint
S3 endpoint URL
Type: null or string
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.s3.insecureSkipTLSVerify
Skip TLS verification
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.s3.region
S3 region
Type: string
Default: "seaweedfs"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.backupStorageLocation.s3.s3ForcePathStyle
Use path-style S3 URLs
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.chart
Velero Helm chart derivation (default: cataCharts.velero)
Type: package
Default: <derivation helm-chart-https-vmware-tanzu.github.io-helm-charts-velero-9.0.1>
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.enable
Whether to enable Velero backup and restore.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.fileSystemBackup.enable
Enable file system backups using restic/kopia
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.fileSystemBackup.uploaderType
Uploader type for file system backups
Type: one of "restic", "kopia"
Default: "kopia"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.local.enable
Enable local development mode using SeaweedFS
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.namespace
Namespace for Velero
Type: string
Default: "velero"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.phase
Deployment phase this component belongs to
Type: string
Default: "operators"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.ref
Computed references for Velero
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.resources.limits.cpu
This option has no description.
Type: string
Default: "1000m"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.resources.limits.memory
This option has no description.
Type: string
Default: "512Mi"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.resources.requests.cpu
This option has no description.
Type: string
Default: "100m"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.resources.requests.memory
This option has no description.
Type: string
Default: "128Mi"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules
Named backup schedules
Type: attribute set of (submodule)
Default:
{
daily = {
schedule = "0 2 * * *";
ttl = "168h";
};
weekly = {
schedule = "0 3 * * 0";
ttl = "720h";
};
}
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.defaultVolumesToFsBackup
Use file-system backup for volumes by default (restic/kopia)
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.enable
Whether this schedule is enabled
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.excludedNamespaces
Namespaces to exclude from backup
Type: list of string
Default:
[
"kube-system"
"velero"
]
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.excludedResources
Resources to exclude from backup
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.includeClusterResources
Whether to include cluster-scoped resources
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.includedNamespaces
Namespaces to include (empty = all)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.includedResources
Resources to include (empty = all)
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.schedule
Cron schedule for backups
Type: string
Default: "0 2 * * *"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.snapshotVolumes
Whether to snapshot PVs (requires volume snapshotter)
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.schedules.<name>.ttl
Time to live for backups (e.g., 720h = 30 days)
Type: string
Default: "720h"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.version
Velero Helm chart version
Type: string
Default: "7.2.1"
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.volumeSnapshotLocation.config
Provider-specific configuration
Type: attribute set of string
Default: { }
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.volumeSnapshotLocation.enable
Enable volume snapshot location
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/backups/velero.nix
velero.volumeSnapshotLocation.provider
Volume snapshot provider
Type: one of "aws", "gcp", "azure", "csi"
Default: "csi"
Declared in: modules/lab/cluster/components/backups/velero.nix
zot.auth.enable
This option has no description.
Type: boolean
Default: false
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.auth.htpasswdSecret
This option has no description.
Type: string
Default: "zot-htpasswd"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.chart
This option has no description.
Type: package
Default: <derivation helm-chart-https-zotregistry.dev-helm-charts-zot-0.1.113>
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.domain
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.enable
Whether to enable Zot OCI-native container registry.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.gateway.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.gateway.gatewayNamespace
This option has no description.
Type: null or string
Default: "kube-system"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.gateway.gatewayRef
This option has no description.
Type: string
Default: "default-gateway"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.http.port
This option has no description.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default: 5000
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.namespace
This option has no description.
Type: string
Default: "zot"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.adminGroups
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.clientId
This option has no description.
Type: string
Default: "zot"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.clientSecretRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.clientSecretRef.key
This option has no description.
Type: string
Default: "client-secret"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.clientSecretRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.enable
Whether to enable OIDC authentication via Kanidm.
Type: boolean
Default: false
Example: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.groupsClaim
This option has no description.
Type: string
Default: "groups"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.issuerUrl
This option has no description.
Type: string
Default: ""
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.readOnlyGroups
This option has no description.
Type: list of string
Default: [ ]
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.scopes
This option has no description.
Type: list of string
Default:
[
"openid"
"email"
"groups"
]
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.oidc.usernameClaim
This option has no description.
Type: string
Default: "preferred_username"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.phase
This option has no description.
Type: string
Default: "apps"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.ref
This option has no description.
Type: attribute set
Default: { }
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.replicas
This option has no description.
Type: positive integer, meaning >0
Default: 1
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.search.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.storage.dedupe
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.storage.rootDirectory
This option has no description.
Type: string
Default: "/var/lib/zot"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.storage.size
This option has no description.
Type: string
Default: "50Gi"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.storage.storageClass
This option has no description.
Type: null or string
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.tls.issuerRef
This option has no description.
Type: null or (submodule)
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.tls.issuerRef.kind
This option has no description.
Type: string
Default: "ClusterIssuer"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.tls.issuerRef.name
This option has no description.
Type: string
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.tls.secretName
This option has no description.
Type: string
Default: "zot-tls"
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.ui.enable
This option has no description.
Type: boolean
Default: true
Declared in: modules/lab/cluster/components/registries/zot.nix
zot.version
This option has no description.
Type: string
Default: "0.1.62"
Declared in: modules/lab/cluster/components/registries/zot.nix
Phases
Phases control the order in which Kubernetes resources are deployed. Not all resources can be applied at once – CRDs must exist before custom resources that use them, operators must be running before their managed resources are created, and databases should be ready before applications that depend on them.
Each phase has a numeric order (lower values deploy first) and a dependsOn list that declares explicit dependencies on other phases. Components write their resources into phase bundles, and the CLI applies phases in order.
Built-in phases
| Phase | Order | Depends on | Description |
|---|---|---|---|
| crds | -10 | – | Custom Resource Definitions. Deployed first so that all subsequent phases can create custom resources. |
| namespaces | -5 | crds | Namespace creation. Ensures target namespaces exist before resources are deployed into them. |
| networking | 0 | namespaces | CNI (Cilium), Gateway API controller (Traefik), and core networking. Must be ready before anything that needs pod networking or ingress. |
| operators | 10 | networking | Operator deployments: cert-manager, external-dns, trust-manager, CNPG operator, kaniop, and others. These controllers must be running before their custom resources are created in later phases. |
| secrets | 20 | operators | Secret management: external-secrets stores, SOPS decryption, and generated secrets. Depends on operators because some secrets are managed by operator-created controllers. |
| infrastructure | 30 | operators, secrets | Core infrastructure services: Kanidm, Prometheus, Loki, Tempo, Zot registry, and similar. These are long-running services that applications depend on. |
| gitops | 40 | operators, secrets | GitOps controllers: ArgoCD. Deployed after operators and secrets so that it has access to credentials and can manage application delivery. |
| databases | 50 | operators, secrets | Database instances: CNPG PostgreSQL clusters, Redis. Depends on operators (for the database controllers) and secrets (for credentials). |
| apps | 90 | infrastructure, databases | Applications: Forgejo, Grafana, and custom apps. Deployed late because they typically depend on databases, identity providers, and other infrastructure. |
| workloads | 100 | infrastructure, databases | User workloads. The final phase for anything that depends on the full platform being ready. |
Phase configuration options
Each phase supports these options:
| Option | Type | Default | Description |
|---|---|---|---|
order | int | (varies) | Numeric ordering. Lower values deploy first. |
dependsOn | list of strings | (varies) | Phases that must complete before this one. |
keepResources | bool | false | Prevent deletion of resources in this phase. |
pruneStrategy | enum | "default" | "default", "never", or "orphan". Controls resource cleanup. |
waitForReady | bool | true | Wait for all resources to become ready before proceeding. |
timeout | string | "10m" | Timeout for this phase’s deployment. |
waitForCRDs | bool | false | Wait for CRDs to be established before deploying. |
crdNames | list of strings | [] | CRD names to wait for when waitForCRDs is true. |
bundles | attrs | {} | Bundles of resources belonging to this phase. |
Bundles
Each phase contains bundles. A bundle is the finest-grained deployment unit and contains:
helmCharts– Helm charts to template and deployresources– Typed Kubernetes resource definitions (Nix attribute sets)yamls– Raw YAML manifests (strings or file paths)createNamespaces– Namespaces to create for this bundle
Components write into bundles by setting phases.<phase>.bundles.<component-name>. Multiple components can write to the same phase but use separate bundles.
Custom phases
You can define custom phases for specialized ordering needs:
phases.pre-apps = {
order = 85;
dependsOn = [ "infrastructure" "databases" ];
waitForReady = true;
timeout = "5m";
};
Components can target custom phases via their phase option:
components.custom.apps.my-app.phase = "pre-apps";
Why ordering matters
Without phase ordering, common failures include:
- Custom resources applied before their CRDs exist (API server rejects them)
- Pods scheduled before the CNI is running (they never get an IP)
- Applications starting before their databases are ready (crash loops)
- OAuth2 clients created before the identity provider is running (registration fails)
- Certificate requests submitted before cert-manager’s webhook is ready (timeouts)
Phases encode these dependencies declaratively so that the CLI (or GitOps engine) applies resources in a safe order every time.
Security
Catallaxy provides three cluster-level security features that derive policies from existing component configuration. Enable with simple toggles — the system generates the right policies.
Pod Security Standards
Kubernetes Pod Security Admission labels control what pods can do in each namespace.
cluster.security.podSecurity = {
enable = true;
default = "restricted"; # "restricted" | "baseline" | "privileged"
};
When enabled, all lab-managed namespaces get PSA labels:
metadata:
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
Per-Namespace Overrides
Components that need elevated privileges (Cilium, kaniop, etc.) can override per namespace:
cluster.security.podSecurity.namespaceOverrides = {
kube-system = "privileged";
kanidm = "baseline";
};
PSA Levels
| Level | Description |
|---|---|
restricted | No host networking, no root, no privilege escalation. Most secure. |
baseline | Prevents known privilege escalations. Allows most workloads. |
privileged | Unrestricted. For system components (CNI, node agents). |
Network Policies
Default-deny network policies restrict pod-to-pod traffic. When enabled, each lab namespace gets a policy that blocks all traffic except:
- DNS (UDP/TCP 53) — pods can resolve names
- Same-namespace — pods in the same namespace can talk to each other
cluster.security.networkPolicies.enable = true;
Cross-Namespace Access
Components that need cross-namespace traffic add their own allow rules in their phase bundles. Use the mkNetworkPolicy helper:
{ config, lib, ... }:
let
catallaxyLib = config._module.args.catallaxyLib or {};
in
lib.mkIf config.cluster.security.networkPolicies.enable {
phases.apps.bundles.my-app.resources.my-app-netpol =
catallaxyLib.mkNetworkPolicy {
name = "allow-gateway-ingress";
namespace = "my-app";
podSelector.matchLabels."app" = "my-app";
policyTypes = ["Ingress"];
ingress = [{
from = [{ namespaceSelector.matchLabels."kubernetes.io/metadata.name" = "kube-system"; }];
ports = [{ port = 8080; }];
}];
};
}
Built-in Components
Built-in components will progressively add their own network policies when this feature is enabled. The default-deny baseline ensures nothing is open by accident.
Audit Logging
Kubernetes API server audit logging records who did what.
cluster.security.auditLogging.enable = true;
Provisioner Behavior
| Provisioner | Behavior |
|---|---|
| k3d | Adds --audit-policy-file and --audit-log-path API server args. Audit policy mounted from host. |
| DOKS | Managed by DigitalOcean. This option is a no-op. |
| Talos | Machine config for audit policy (future). |
k3d Audit Policy
When enabled on k3d, an audit policy file is mounted at /etc/kubernetes/audit/policy.yaml. The default policy logs:
- All authentication events
- All resource creation/deletion
- Metadata for read operations
Audit logs are written to /var/log/kubernetes/audit.log inside the k3d node container.
Enabling All Security Features
# In your cluster config:
cluster.security = {
podSecurity.enable = true;
networkPolicies.enable = true;
auditLogging.enable = true;
};
This gives you defense-in-depth: pod restrictions, network segmentation, and an audit trail — all derived from your existing lab configuration.
Image Management
Catallaxy provides declarative control over container images for reproducibility and security.
Image Pins
Pin container images at the lab level with optional digest verification:
lab.images.pins = {
grafana = {
image = "docker.io/grafana/grafana";
tag = "11.4.0";
digest = "sha256:abc123..."; # Optional — ensures bit-for-bit reproducibility
};
prometheus = {
image = "quay.io/prometheus/prometheus";
tag = "v3.0.0";
};
};
Each pin computes a ref — the full image reference string:
| Configuration | ref value |
|---|---|
| tag only | docker.io/grafana/grafana:11.4.0 |
| digest only | docker.io/grafana/grafana@sha256:abc123 |
| tag + digest | docker.io/grafana/grafana:11.4.0@sha256:abc123 |
Components can reference pins: lab.images.pins.grafana.ref
Image Policy
Require Digest
When enabled, the lint check errors on any container image without a digest pin:
lab.images.requireDigest = true;
This enforces that every image in your rendered manifests is pinned to a specific build. Tags are mutable (a registry can serve a different image for the same tag), but digests are immutable.
Allowed Registries
Restrict which registries images can come from:
lab.images.allowedRegistries = [
"ghcr.io"
"registry.k8s.io"
"docker.io"
];
The lint check warns about images from registries not in this list. Leave empty (default) to allow all registries.
Lint Check
The image-pin lint check scans rendered manifests for container image references in Deployments, StatefulSets, DaemonSets, Jobs, and CronJobs.
It always warns about:
:latesttags — mutable and non-reproducible
With policy enabled:
- Missing digests (when
requireDigest = true) — Error - Unapproved registries (when
allowedRegistriesis set) — Warning
Suppression
Skip the check for specific resources:
metadata:
annotations:
catallaxy.io/lint-skip: image-pin
Pull-Through Cache
For rate limiting protection, use Zot as a pull-through cache:
components.zot = {
enable = true;
sync.enable = true; # Pull-through cache from Docker Hub, Quay, GHCR, registry.k8s.io
};
This caches images locally on first pull. Combined with image pins, you get both availability and reproducibility.
Lint System
Catallaxy’s lint system validates rendered manifests against universal properties. It’s the primary mechanism for catching configuration errors before deployment.
Built-in Checks
| Check | What it validates |
|---|---|
schema | Every resource has apiVersion, kind, metadata.name |
identity | No duplicate (apiVersion, kind, namespace, name) tuples |
prefix | Resources and namespaces use the lab prefix |
selector | Service selectors match workload pod labels |
reference | ConfigMap/Secret references point to existing resources |
projection-ref | secretKeyRef names match declared projections with correct phase/namespace |
image-pin | Container images use digest pins and approved registries |
crd-schema | Custom Resources validate against CRD OpenAPI schemas |
missing-crd | Warns when a CR has no matching CRD in the manifest set |
Running Lint
cata lab lint # Lint the default lab
cata lab lint --path <pkg> # Lint a pre-built lab package
In CI, nix flake check runs lint on all example labs automatically.
Skipping Checks
Per-resource:
metadata:
annotations:
catallaxy.io/lint-skip: reference,image-pin
Per-run:
cata lab lint --skip image-pin --skip crd-schema
Custom Lint Checks
Define custom property checks in Nix that run shell commands on rendered manifests:
lab.lint.checks = {
no-default-namespace = {
description = "Resources must not use the default namespace";
severity = "error";
command = ''
results=$(yq -N 'select(.metadata.namespace == "default") | .metadata.name' "$FILE" 2>/dev/null)
if [ -n "$results" ]; then
echo "Found resources in default namespace: $results"
exit 1
fi
'';
};
no-latest-tags = {
description = "Container images must not use :latest";
severity = "warning";
command = ''
results=$(yq -N '
select(.kind == "Deployment" or .kind == "StatefulSet") |
.spec.template.spec.containers[] |
select(.image | test(":latest$")) |
.image
' "$FILE" 2>/dev/null)
if [ -n "$results" ]; then
echo "$results"
exit 1
fi
'';
};
require-resource-limits = {
description = "Containers must have resource limits";
severity = "warning";
command = ''
results=$(yq -N '
select(.kind == "Deployment" or .kind == "StatefulSet") |
.spec.template.spec.containers[] |
select(.resources.limits == null) |
.name
' "$FILE" 2>/dev/null)
if [ -n "$results" ]; then
echo "Missing resource limits: $results"
exit 1
fi
'';
};
};
Shell Command Interface
Each check receives:
$FILE— path to a YAML manifest file$CLUSTER— name of the cluster being checked
Available tools: yq, jq, standard Unix tools.
Return values:
- Exit 0 → check passes
- Non-zero → check fails; stdout becomes the diagnostic message
Severity
"error"— fails the lint (non-zero exit fromcata lab lint)"warning"— reported but doesn’t fail
Nix Assertions (Config-Level Properties)
For properties that can be checked at Nix evaluation time (before rendering), use assertions:
config.assertions = [
{
assertion = config.components.my-app.enable -> config.components.cnpg.enable;
message = "my-app requires PostgreSQL (enable components.cnpg)";
}
{
assertion = config.cluster.security.networkPolicies.enable || !config.components.my-app.enable;
message = "my-app requires network policies to be enabled";
}
];
Assertions fire at nix eval time — before any manifests are rendered. They catch configuration-level contradictions immediately.
Testing Strategy
Catallaxy’s testing is property-based:
- Nix assertions — config-level properties checked at eval time
- Lint checks — manifest-level properties checked on rendered YAML
- E2E — deploy examples and verify they work
nix flake check # Runs lint on all example labs (CI-friendly)
cata lab up # E2E: deploy and verify
cata lab down # Clean up
No traditional unit tests — correctness comes from universal properties that hold across all configurations.
Extending Catallaxy
Catallaxy is designed to be extended without forking. Teams can add custom components, Helm charts, provisioners, and operational commands by writing NixOS modules that compose with the built-in components.
Architecture
The extensibility model is simple: the Nix module system is the extension mechanism.
Components write to a shared namespace (phases.${name}.bundles.${name}), and the rendering pipeline consumes those bundles to produce Kubernetes manifests. The bundle type is the stable contract:
bundleType = {
resources = attrsOf kubernetesResourceType; # Typed K8s resources
helmCharts = attrsOf helmChartType; # Helm charts with values
yamls = listOf (either str path); # Raw YAML strings or files
createNamespaces = listOf str; # Namespaces to create
};
Everything upstream of bundles (component options, user config) is the frontend. Everything downstream (rendering, strategy layout) is the backend. Your custom modules operate in the frontend — declaring options and producing bundles.
Getting Started
nix flake init -t github:onepunch/catallaxy#consumer
This creates a consumer flake with a working custom component example.
Extension Points
| What | How | Example |
|---|---|---|
| Custom component | Module writing to phases.bundles | Writing Components |
| Custom Helm chart | helmCharts.${name} in a bundle | Helm Charts |
| Custom phase | phases.${name}.order = N | Phase Ordering |
| Secret projections | secrets.projections.${name} | Secrets |
| Ops commands | ops.${name} | Ops Commands |
| Lifecycle hooks | lifecycle.teardown | Lifecycle |
Writing Custom Components
A component is a NixOS module that declares high-level options and writes Kubernetes resources into phase bundles. This is the same pattern used by all built-in components (ArgoCD, Prometheus, Kanidm, etc.).
The Pattern
Every component follows three parts:
- Options — what the user configures
- Refs — computed values other components can read
- Phase writer — produces bundles when enabled
{ config, lib, ... }:
let
cfg = config.components.my-app;
in
{
# 1. Options
options.components.my-app = {
enable = lib.mkEnableOption "my-app";
phase = lib.mkOption { type = lib.types.str; default = "apps"; };
namespace = lib.mkOption { type = lib.types.str; default = "my-app"; };
domain = lib.mkOption { type = lib.types.str; };
ref = lib.mkOption { type = lib.types.attrs; readOnly = true; };
};
config = lib.mkMerge [
# 2. Refs (always computed, even when disabled)
{
components.my-app.ref = {
namespace = cfg.namespace;
url = "http://my-app.${cfg.namespace}.svc.cluster.local";
};
}
# 3. Phase writer (only when enabled)
(lib.mkIf cfg.enable {
phases.${cfg.phase}.bundles.my-app = {
resources = { /* K8s resources */ };
helmCharts = { /* Helm charts */ };
createNamespaces = [ cfg.namespace ];
};
})
];
}
Bundle Type
The bundle is the contract between your component and the rendering pipeline:
resources
Typed Kubernetes resource definitions as Nix attribute sets:
resources.my-deployment = {
apiVersion = "apps/v1";
kind = "Deployment";
metadata = { name = "my-app"; namespace = cfg.namespace; };
spec = { /* ... */ };
};
helmCharts
Helm charts with values:
helmCharts.my-app = {
chart = myChartDerivation; # A Nix derivation containing the chart
releaseName = "my-app";
namespace = cfg.namespace;
createNamespace = true;
values = {
replicaCount = 3;
image.tag = cfg.version;
};
};
yamls
Raw YAML strings or file paths (for resources that don’t fit the typed model):
yamls = [
./manifests/custom-crd.yaml
(builtins.toJSON { apiVersion = "v1"; kind = "ConfigMap"; /* ... */ })
];
createNamespaces
Namespaces that should be created before this bundle deploys:
createNamespaces = [ cfg.namespace ];
Phase Ordering
Components target a phase by name. Built-in phases and their order:
| Phase | Order | Use for |
|---|---|---|
| crds | -10 | Custom Resource Definitions |
| namespaces | -5 | Namespace creation (automatic) |
| networking | 0 | CNI, Gateway, DNS |
| operators | 10 | Controllers and operators |
| secrets | 20 | Secret management |
| infrastructure | 30 | Core services (identity, monitoring) |
| gitops | 40 | GitOps controllers |
| databases | 50 | Database instances |
| apps | 90 | Applications |
| workloads | 100 | User workloads |
Custom phases can be defined with any order value.
Using mkComponent
For simple components, use the mkComponent helper:
# In your flake:
catallaxy.lib.mkComponent {
name = "my-app";
phase = "apps";
options = {
domain = lib.mkOption { type = lib.types.str; };
replicas = lib.mkOption { type = lib.types.int; default = 1; };
};
module = cfg: {
phases.apps.bundles.my-app = {
helmCharts.my-app = {
chart = myChart;
releaseName = "my-app";
namespace = cfg.namespace;
values = { host = cfg.domain; replicas = cfg.replicas; };
};
createNamespaces = [ cfg.namespace ];
};
};
}
Cross-Component References
Components expose computed values via ref for other components to consume:
# In your component:
components.my-app.ref = {
url = "http://my-app.${cfg.namespace}.svc.cluster.local:8080";
namespace = cfg.namespace;
};
# In another component:
config.components.my-app.ref.url # → "http://my-app.my-app.svc.cluster.local:8080"
Consumer Flake
Pass your component modules to mkLab:
{
inputs.catallaxy.url = "github:onepunch/catallaxy";
outputs = { catallaxy, ... }:
catallaxy.lib.eachDefaultSystem (system: {
labs."my-platform" = (catallaxy.${system}.mkLab {
modules = [ ./lab.nix ./components/my-app.nix ];
}).config.lab.out.cliConfig;
});
}
Contributing Guide
Setting up the development environment
All build tools are provided by the Nix dev shell:
nix develop
This gives you cargo, talosctl, kubectl, kapp, helm, k3d, and all other tools needed to build and test Catallaxy.
Building
Rust CLI
cd cli/
cargo build
cargo watch -x run # rebuild on changes
Full wrapped CLI (Nix)
nix build .#cata
The Nix-built binary includes all runtime tools in its PATH (kubectl, kapp, helm, etc.), so it works without entering the dev shell.
Rendered manifests
nix build '.#labPackages.x86_64-linux."homelab.local"'
This evaluates the example lab modules and renders all Kubernetes manifests, which is useful for verifying that module changes produce correct output.
Checking your work
Full check suite
nix flake check
This runs:
- CLI build
- Nix formatting check (nixfmt)
- Rust formatting check (rustfmt)
cata lab linton all example labs
Formatting
nix fmt
Formats all Nix, Rust, and YAML files. Run this before submitting changes.
Code style
Nix
- Minimal comments. Prefer clear naming and structure over inline documentation.
- Use
optionalAttrsorif/then/elsefor conditional attribute values. Do NOT usemkIfinside values passed toresourcesoryamls– it does not work as expected in that context. - Components follow the single-file pattern: options and phase writer in one file. See Adding Components.
refattributes are alwaysreadOnlyand always set (even when the component is disabled).
Rust
- Standard Rust conventions. Format with
rustfmt(included innix fmt). - The CLI shells out to external tools (
nix eval,kapp,kubectl,helm) rather than reimplementing their logic.
General
- No auto-generated comments or boilerplate.
- Keep diffs small and focused.
- Test changes with
nix flake checkbefore submitting.
Project structure
| Path | Description |
|---|---|
cli/src/ | Rust CLI source |
modules/lab/ | Lab-level Nix modules |
modules/lab/cluster/ | Cluster-level modules |
modules/lab/cluster/components/ | Component modules |
modules/lab/cluster/phases/ | Phase definitions |
lib/ | Shared Nix libraries (eval, render, charts) |
lib/renderers/ | Output strategies (kapp, argocd, fleet) |
examples/labs/ | Example lab configurations |
docs/ | Documentation (this mdBook site) |
Testing
There are no traditional unit tests yet. The CLI has assert_cmd in dev-dependencies but no test files. Validation is done via nix flake check, which evaluates all example labs and runs cata lab lint.
To manually test changes:
- Run
nix flake checkto verify the build and lint pass. - Build rendered manifests to inspect the output:
nix build '.#labPackages.x86_64-linux."homelab.local"' - For runtime testing, stand up the example lab:
cata --flake ./examples/labs#homelab lab up
Adding Components
Components are self-contained infrastructure units. Each component is a single Nix file that declares its configuration options and writes Kubernetes resources into phase bundles when enabled.
Step 1: Create the component file
Create a new file at modules/lab/cluster/components/<category>/<name>.nix.
If the component fits an existing category (e.g., observability, databases, pki), place it there. If you need a new category, create a directory for it.
Step 2: Write the component module
Follow this template:
{ config, lib, cataCharts, ... }:
let
inherit (lib) mkOption mkEnableOption mkIf types;
cfg = config.components.<name>;
in
{
options.components.<name> = {
enable = mkEnableOption "<Name>";
phase = mkOption {
type = types.str;
default = "<phase>";
description = "Deployment phase";
};
namespace = mkOption {
type = types.str;
default = "<namespace>";
};
chart = mkOption {
type = types.package;
default = cataCharts.<name>.chart;
description = "Helm chart to use";
};
# Component-specific options go here
ref = mkOption {
type = types.attrs;
readOnly = true;
description = "Cross-component reference values";
};
};
config = lib.mkMerge [
# Computed refs -- always available, even when disabled.
# This lets other components reference this component's values
# without requiring it to be enabled.
{
components.<name>.ref = {
namespace = cfg.namespace;
# Add any values other components might need:
# endpoint = "http://<name>.${cfg.namespace}.svc:8080";
};
}
# Phase writer -- only active when enabled
(mkIf cfg.enable {
phases.${cfg.phase}.bundles.<name> = {
createNamespaces = [ cfg.namespace ];
helmCharts.<name> = {
chart = cfg.chart;
namespace = cfg.namespace;
values = {
# Helm values go here
};
};
# Optional: typed Kubernetes resources
# resources = { ... };
# Optional: raw YAML manifests
# yamls = [ ... ];
};
})
];
}
Key conventions
refis always set. Even when the component is disabled,refvalues must be available so other components can reference them without conditional checks.mkIfis fine at the top level (around the phase writer block), but do NOT usemkIfinsideresourcesoryamlsvalues. UseoptionalAttrsorif/then/elseinstead.- Charts come from
cataCharts. Register your chart inlib/charts.nixfirst (see Adding Charts), then reference it ascataCharts.<name>.chart. - CRDs go in the
crdsphase. If your chart has CRDs, write them into a separate bundle:
(mkIf cfg.enable {
phases.crds.bundles."<name>-crds".yamls = [ cataCharts.<name>.crds ];
phases.${cfg.phase}.bundles.<name>.helmCharts.<name> = { ... };
})
Step 3: Register the component
Add an import to the category’s default.nix:
# modules/lab/cluster/components/<category>/default.nix
{ ... }:
{
imports = [
./<existing-component>.nix
./<name>.nix # add this line
];
}
Step 4: Register a new category (if needed)
If you created a new category directory, add it to the top-level component registry:
# modules/lab/cluster/components/default.nix
{ ... }:
{
imports = [
./backups
./cni
# ...existing categories...
./<new-category> # add this line
];
}
And create a default.nix in your new category directory:
# modules/lab/cluster/components/<new-category>/default.nix
{ ... }:
{
imports = [
./<name>.nix
];
}
Step 5: Verify
Run the full check suite:
nix flake check
This evaluates all example labs and runs lint, catching missing imports, type errors, and evaluation failures.
To inspect the rendered output:
nix build '.#labPackages.x86_64-linux."homelab.local"'
Cross-component references
Components can reference other components via the ref attribute. This is how services wire together without hardcoding values:
{ config, ... }:
let
certManagerRef = config.components.cert-manager.ref;
in
{
# Use certManagerRef.caBundleConfigMap, certManagerRef.caBundleKey, etc.
}
For cross-cluster references, use the lab argument:
{ config, lab, ... }:
{
components.otel-collector.exporters.otlp.endpoint =
lab.clusters.obs.components.tempo.ref.otlpGrpc;
}
Adding Charts
Helm charts are centrally managed in lib/charts.nix. Each chart is fetched at Nix evaluation time with a pinned version and integrity hash.
Step 1: Add the chart definition
Open lib/charts.nix and add an entry to the chartDefs attribute set:
chartDefs = {
# ... existing charts ...
my-chart = {
repo = "https://example.github.io/helm-charts";
chart = "my-chart";
version = "1.2.3";
chartHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
};
Required fields
| Field | Description |
|---|---|
repo | Helm repository URL. Supports https:// and oci:// prefixes. |
chart | Chart name within the repository. |
version | Exact chart version to fetch. |
chartHash | SRI hash of the chart archive. Use a dummy value first, then fix it (see below). |
Step 2: Get the chart hash
Set chartHash to an empty string or a dummy value, then build. Nix will report a hash mismatch and show the correct hash:
nix build .#cata 2>&1 | grep "got:"
Copy the sha256-... hash from the error output and paste it into chartHash.
Step 3: Add CRDs (if applicable)
If the chart installs CRDs, add a crd attribute. There are three CRD source types:
From the chart’s crds/ directory
my-chart = {
repo = "...";
chart = "my-chart";
version = "1.2.3";
chartHash = "sha256-...";
crd = {
type = "chart";
};
};
From a URL
my-chart = {
# ...
crd = {
type = "url";
url = "https://github.com/example/releases/download/v1.2.3/crds.yaml";
hash = "sha256-...";
};
};
From a GitHub repository
my-chart = {
# ...
crd = {
type = "github";
owner = "example";
repo = "my-project";
rev = "v1.2.3";
hash = "sha256-...";
crdPath = "config/crd/bases";
};
};
The hash for GitHub sources is the fetchFromGitHub hash. Use the same dummy-value-and-fix approach to obtain it.
Step 4: Use the chart in a component
Reference the chart in your component module via cataCharts:
{ cataCharts, ... }:
{
options.components.my-component = {
chart = mkOption {
type = types.package;
default = cataCharts.my-chart.chart;
};
};
config = mkIf cfg.enable {
# Deploy CRDs in the crds phase
phases.crds.bundles.my-component-crds.yamls = [ cataCharts.my-chart.crds ];
# Deploy the chart in the appropriate phase
phases.${cfg.phase}.bundles.my-component.helmCharts.my-component = {
chart = cfg.chart;
namespace = cfg.namespace;
values = { ... };
};
};
}
The cataCharts.<name> attribute set provides:
| Attribute | Description |
|---|---|
chart | The fetched chart derivation (passed to Helm) |
crds | CRD derivation, or null if no CRDs are defined |
version | Chart version string |
Step 5: Verify
nix flake check
This ensures the chart fetches correctly and all labs that use it still evaluate.
Roadmap
Completed features are in the CHANGELOG. This page shows what’s planned.
Next
- Management cluster pivot — bootstrap on k3d, self-provision in cloud, migrate state, destroy bootstrap
- Registry mirror integration — configure containerd to use lab Zot as pull-through cache
- Component network policies — built-in components declare cross-namespace allow rules when
networkPolicies.enable
Later
- On-premises support (Talos Linux on bare metal)
- Performance benchmarking for large multi-cluster labs
- Computed SBOMs from image set and rendered manifests
cata images lock— resolve tags to digests automatically (lockfile pattern)
Ideas
- Automated testing framework for lab configurations
- Global image registry rewrite for air-gapped environments