02. Local setup and first run
This content is for the v0.1 version. Switch to the latest version for up-to-date documentation.
In this tutorial you will deploy one tiny Kix cluster to kind, port-forward to it, and make one config edit. The point is to feel the loop:
- Edit the cluster or package.
- Check what Kix can prove before touching the cluster.
- Deploy the checked activation.
- Verify with
kix pf,curl, orkubectl.
Prerequisites
Section titled “Prerequisites”- Read Orientation: what Kix is and why it exists.
- Install Nix with flakes enabled.
- Have Docker, Colima, or OrbStack running.
- Have
kind,kubectl, and thekixCLI available. The next section shows one way to get them.
Start From The Example Repo
Section titled “Start From The Example Repo”The runnable examples live in the public kix-examples repo:
❱ git clone https://github.com/kix-ops/kix-examples.git❱ cd kix-examples If you already have the repo, use that checkout instead. The commands below assume you are at the repo root.
Open the files for the first example:
flake.nixtutorials/02-hello-world/cluster.nixtutorials/02-hello-world/README.mdkind-config.yamlYou do not need to understand all of them yet. For now:
flake.nixexposes the example clusters by name;tutorials/02-hello-world/cluster.nixdefines the first cluster;kind-config.yamlcreates a local kind cluster namedkix-demo.
Enter A Shell With The Tools
Section titled “Enter A Shell With The Tools”If your machine already has kix, kind, and kubectl on PATH, you can use
your normal shell. If you need the Kix CLI, install it from the public
kixpkgs flake:
❱ nix profile install github:kix-run/kixpkgs#kix Keep Docker, Colima, or OrbStack running separately. kind needs a Docker-compatible daemon to create the local cluster.
Check that Kix can see the example clusters:
❱ 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-python
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 You should see 02-hello-world in the output. If you are not in the example
repo, point Kix at it explicitly:
❱ kix --flake /path/to/kix-examples list clusters The --flake flag tells Kix which flake to evaluate. Without it, Kix uses the
current directory.
Create The Local Cluster
Section titled “Create The Local Cluster”Start Docker, then create the kind cluster:
❱ kind create cluster --config kind-config.yaml This creates a single-node cluster named kix-demo and sets your current
kubectl context to kind-kix-demo.
Check that Kubernetes is reachable:
❱ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:57687
CoreDNS is running at https://127.0.0.1:57687/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. ❱ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kix-docs-control-plane NotReady control-plane 4s v1.35.0 If you already have this kind cluster, kind will say it exists. That is fine;
continue with the deploy step.
Your First Kix Deployment
Section titled “Your First Kix Deployment”Deploy the first Kix example:
❱ kix deploy 02-hello-world -y Show output
Building cluster '02-hello-world'...
Cluster 02-hello-world: 10 manifests
Connecting to cluster...
No previous activation on cluster — first deploy.
Reading live cluster state...
_cluster
~ cluster-level resources (4 added)
kube-system
+ platform-dns (0 resources)
tutorial-02
+ hello-world 1.27 (3 resources)
Plan: cluster-level changes, 2 added
Resources: 4 real content, 0 dep-affected
plan: 10 nodes
~ Namespace/kube-system configured
✔ Namespace/kube-system ready
+ Namespace/tutorial-02 created
✔ Namespace/tutorial-02 ready
+ CustomResourceDefinition/packageinstances.kix.run created
+ CustomResourceDefinition/activations.kix.run created
+ ConfigMap/hello-world@tutorial-02 created
✔ ConfigMap/hello-world@tutorial-02 ready
+ Deployment/hello-world@tutorial-02 created
✔ CustomResourceDefinition/packageinstances.kix.run ready
✔ CustomResourceDefinition/activations.kix.run ready
+ PackageInstance/platform-dns@kube-system created
✔ PackageInstance/platform-dns@kube-system ready
✔ Deployment/hello-world@tutorial-02 ready
+ Service/hello-world@tutorial-02 created
✔ Service/hello-world@tutorial-02 ready
+ PackageInstance/hello-world@tutorial-02 created
✔ PackageInstance/hello-world@tutorial-02 ready
+ Activation/02-hello-world-rh3pdaspsdxk created
✔ Activation/02-hello-world-rh3pdaspsdxk ready
• activation '02-hello-world-rh3pdaspsdxk' → Active
Deploy complete: 9 created, 1 configured, 0 unchanged, 0 failed The -y flag skips the confirmation prompt. On the first deploy, Kix builds the
cluster, sees there is no previous activation, and applies the resources
wave-by-wave — the order you see comes from the deploy graph.
List the packages installed in this Kix cluster:
❱ kix list packages --cluster 02-hello-world
NAME VERSION OWNER STATUS
hello-world 1.27 app-team installed [tutorial-02]
platform-dns - - import [kube-system]
platform-storage - - import [kube-system] You should see an installed hello-world instance. The import rows are
platform pieces (DNS, storage) Kix pulls in automatically — later tutorials
explain them. You can also ask Kubernetes
directly:
❱ kubectl get pods -n tutorial-02
NAME READY STATUS RESTARTS AGE
hello-world-6f4588d4c5-pwt94 1/1 Running 0 21s❱ kubectl get svc -n tutorial-02
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world ClusterIP 10.96.142.137 <none> 80/TCP 2s Reach The Service
Section titled “Reach The Service”The first example installs an echo-server package instance named
hello-world. Use kix pf to port-forward to its primary workload:
❱ kix pf 02-hello-world hello-world 8080:80 Leave that command running. In another terminal, call the service:
❱ curl http://localhost:8080/
Hello from Kix! Stop the port-forward with Ctrl-C.
kix pf resolves the package instance to the workload Kix built, then delegates
to kubectl port-forward. The package name can also be written as
namespace/name when a cluster has duplicate instance names, but this first
cluster only has one.
Make One Edit
Section titled “Make One Edit”Open tutorials/02-hello-world/cluster.nix and find this instance:
hello-world = { # `packages.echo-server` ships in the public kixpkgs # repository, along with many others. # It serves a simple fixed message over HTTP. package = packages.echo-server;
# `config` is whatever the package's options accept. # echo-server's `message` becomes the body of every response. config = { message = "Hello from Kix!"; }; };Change the message:
config = { message = "Hello from my laptop!";};Deploy again:
❱ kix deploy 02-hello-world -y Show output
Building cluster '02-hello-world'...
Cluster 02-hello-world: 10 manifests
Connecting to cluster...
Active activation: 02-hello-world-rh3pdaspsdxk (rh3pdasp...)
Reading live cluster state...
tutorial-02
~ hello-world 1.27 (1 changed, 3 dep-affected)
Plan: 1 updated, 1 unchanged
Resources: 1 real content, 3 dep-affected
plan: 10 nodes
~ ConfigMap/hello-world@tutorial-02 configured
✔ ConfigMap/hello-world@tutorial-02 ready
~ Deployment/hello-world@tutorial-02 configured
✔ Deployment/hello-world@tutorial-02 ready
~ Service/hello-world@tutorial-02 configured
✔ Service/hello-world@tutorial-02 ready
~ PackageInstance/hello-world@tutorial-02 configured
✔ PackageInstance/hello-world@tutorial-02 ready
+ Activation/02-hello-world-ai8hpfnhamfs created
✔ Activation/02-hello-world-ai8hpfnhamfs ready
• activation '02-hello-world-rh3pdaspsdxk' → Superseded
• activation '02-hello-world-ai8hpfnhamfs' → Active
Deploy complete: 1 created, 4 configured, 5 unchanged, 0 failed Port-forward and curl again:
❱ kix pf 02-hello-world hello-world 8080:80 In another terminal:
❱ curl http://localhost:8080/
Hello from my laptop! The response should show your new message.
That edit is small, but it proves the core loop: Kix evaluated the flake, rebuilt the manifests, applied the changed workload, and left you with a normal Kubernetes Service and Pod.
Before Moving On
Section titled “Before Moving On”You have now used:
kix list clustersto discover cluster names;kix deploy <cluster> -yto apply one cluster;kix list packages --cluster <cluster>to inspect installed packages;kix pf <cluster> <package> <local>:<remote>to reach a workload.
The next tutorial steps back from the running cluster and looks at the repo shape that made those commands work.