Skip to content
kix /docs
Install the CLI

How-to guide Start and inspect a Kix project

Use mkFlake in a consuming repo

Expose Kix clusters and package inputs from an infrastructure repository flake.

Use kixpkgs.lib.mkFlake in the repository that owns your cluster definitions. It exposes the cluster outputs that the Kix CLI discovers.

Create a flake.nix and declare nixpkgs and kixpkgs:

flake.nix
{
description = "Application infrastructure";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
kixpkgs.url = "github:kix-run/kixpkgs";
kixpkgs.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs: inputs.kixpkgs.lib.mkFlake {
inherit inputs;
clusters.production = ./clusters/production.nix;
};
}

Following the same nixpkgs input keeps package evaluation on one nixpkgs revision.

The examples repository registers each cluster by name:

flake.nix
outputs =
inputs:
inputs.kixpkgs.lib.mkFlake {
inherit inputs;
clusters = {
"02-hello-world" = ./tutorials/02-hello-world/cluster.nix;
"06-service-dep" = ./tutorials/06-service-dep/cluster.nix;
"08-namespace-deps" = ./tutorials/08-namespace-deps/cluster.nix;
"09-typed-options" = ./tutorials/09-typed-options/cluster.nix;
"10-reuse-packages" = ./tutorials/10-reuse-packages/cluster.nix;
"19-scorecards" = ./tutorials/19-scorecards/cluster.nix;
"how-to-application" = ./how-to/application/cluster.nix;
"how-to-adoption" = ./how-to/adoption/cluster.nix;
"how-to-stateful-migration" = ./how-to/adoption/stateful-before-cluster.nix;
"how-to-adoption-takeover" = ./how-to/adoption/takeover-cluster.nix;
"how-to-helm-bridge" = ./how-to/adoption/helm-bridge-cluster.nix;
"how-to-auto-instantiation" = ./how-to/auto-instantiation/cluster.nix;
"how-to-composition" = ./how-to/composition/cluster.nix;
"how-to-fragments" = ./how-to/composition/fragments-cluster.nix;
"how-to-multi-env" = ./how-to/composition/multi-env-cluster.nix;
"how-to-package-storage" = ./how-to/package-stacks/storage-cluster.nix;
"how-to-package-stackgres" = ./how-to/package-stacks/stackgres-cluster.nix;
"how-to-package-monitoring" = ./how-to/package-stacks/monitoring-cluster.nix;
"how-to-package-monitoring-loki" = ./how-to/package-stacks/monitoring-loki-cluster.nix;
"how-to-package-cilium" = ./how-to/package-stacks/cilium-cluster.nix;
"how-to-package-valkey" = ./how-to/package-stacks/valkey-cluster.nix;
"how-to-package-velero" = ./how-to/package-stacks/velero-cluster.nix;
"how-to-package-victoria-metrics" = ./how-to/package-stacks/victoria-metrics-cluster.nix;
"how-to-platform-gateway" = ./how-to/platform/gateway-cluster.nix;
"how-to-platform-hostpath" = ./how-to/platform/hostpath-cluster.nix;
"how-to-platform-ingress" = ./how-to/platform/ingress-cluster.nix;
"how-to-platform-monitoring" = ./how-to/platform/monitoring-cluster.nix;
"how-to-platform-network-policy" = ./how-to/platform/network-policy-cluster.nix;
"how-to-platform-secrets" = ./how-to/platform/secrets-cluster.nix;
"how-to-platform-sops" = ./how-to/platform/sops-secrets-cluster.nix;
"how-to-platform-cloudflare-tunnel" = ./how-to/platform/cloudflare-tunnel-cluster.nix;
};
};

View source on GitHub ↗

Each value under clusters is a cluster function. Its attribute name becomes the CLI cluster name, while the file’s kix.buildCluster.name becomes the cluster identity recorded in manifests and activations.

For a single project, a compact registration is enough:

flake.nix
outputs = inputs: inputs.kixpkgs.lib.mkFlake {
inherit inputs;
clusters.application = ./cluster.nix;
};

clusterModules lists modules every cluster in the flake starts from, ahead of the cluster’s own. Use it for a setting the repository wants everywhere, such as making scorecard findings fail the build:

flake.nix
outputs = inputs: inputs.kixpkgs.lib.mkFlake {
inherit inputs;
clusters.production = ./clusters/production.nix;
clusterModules = [ { scorecard.maxSeverity = "error"; } ];
};

A cluster that needs a different value sets the option itself with lib.mkForce.

Evaluating a cluster does not check the option contract. List the packages the repository defines under packages, and the flake gets the check option-contract-<name> for each one:

flake.nix
outputs = inputs: inputs.kixpkgs.lib.mkFlake {
inherit inputs;
clusters.production = ./clusters/production.nix;
packages.billing-api = ./packages/billing-api;
};

nix flake check then fails when a default of billing-api would be partly discarded by an instance that sets part of the option, at any availability level the package can run at.

Create or update flake.lock after adding the inputs:

infrastructure/
❱ nix flake lock

Commit flake.nix and flake.lock together. Other machines and CI will then evaluate the same Kix and nixpkgs revisions.

List the clusters exposed by the flake:

kix-examples/
❱ kix list clusters
 NAME                              
 02-hello-world                    
 06-service-dep                    
 08-namespace-deps                 
 09-typed-options                  
 10-reuse-packages                 
 19-scorecards                     
 how-to-adoption                   
 how-to-adoption-takeover          
 how-to-application                
 how-to-auto-instantiation         
 how-to-composition                
 how-to-fragments                  
 how-to-helm-bridge                
 how-to-multi-env                  
 how-to-package-cilium             
 how-to-package-monitoring         
 how-to-package-monitoring-loki    
 how-to-package-stackgres          
 how-to-package-storage            
 how-to-package-valkey             
 how-to-package-velero             
 how-to-package-victoria-metrics   
 how-to-platform-cloudflare-tunnel 
 how-to-platform-gateway           
 how-to-platform-hostpath          
 how-to-platform-ingress           
 how-to-platform-monitoring        
 how-to-platform-network-policy    
 how-to-platform-secrets           
 how-to-platform-sops              
 how-to-stateful-migration

If the flake is not in the current directory, pass it explicitly:

❱ kix list clusters --flake ./infrastructure

You can now use the discovered names with check, build, diff, deploy, and the other cluster commands.