Setting up Kubernetes on NixOS
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Setting up Kubernetes on NixOS is different from a conventional Linux distribution because the cluster configuration is declared in configuration.nix rather than assembled from imperative install steps. The NixOS Kubernetes module can enable the control-plane and node services directly, which makes a small development cluster reproducible once the module options are correct.
Start with the Built-In NixOS Module
For a straightforward single-node development cluster, the built-in services.kubernetes module is the simplest place to start. NixOS supports enabling cluster components individually, but for most first setups the role-based configuration is easier.
A minimal single-node configuration looks like this:
The important option here is masterAddress. The NixOS module requires it, and every node in the cluster must be able to resolve and reach that address. For a local single-node cluster, localhost is acceptable.
Apply the Configuration
After editing /etc/nixos/configuration.nix, rebuild the system:
Then check the services:
Service names can vary depending on the enabled components, but the main goal is to confirm that the API server, kubelet, and supporting services started without certificate or networking errors.
Access the Cluster with kubectl
When easyCerts is enabled, NixOS generates an administrative kubeconfig for the cluster. Export it before using kubectl as an administrator:
On a working single-node setup, you should see the local machine listed as a node. This kubeconfig is typically owned by root, so administrative access usually happens from a root shell or with sudo.
A Multi-Node Shape
For a worker node, the module configuration is smaller. The host only needs the node role plus a reachable master address.
Example worker configuration:
After the worker machine is rebuilt, NixOS provides a helper script named nixos-kubernetes-node-join. The usual flow is:
- obtain the bootstrap token from the master
- feed that token to
nixos-kubernetes-node-joinon the worker - let certificate services issue and install the required keypairs
That is much less manual than hand-assembling kubeconfigs, but it still depends on working DNS and network reachability.
Networking and Firewall Reality
Most early failures are not about Kubernetes itself. They are about networking:
- '
masterAddressdoes not resolve on the worker' - the firewall blocks pod or control-plane traffic
- container networking is up, but DNS inside the cluster is not
If the cluster looks half alive, inspect logs before editing random options:
For a simple local development cluster, some users choose to relax firewall rules while proving the setup works, then harden them afterward. The exact rule set depends on the cluster topology and CNI behavior.
When to Use K3s Instead
The built-in Kubernetes module is powerful, but it is still a full Kubernetes stack. If your real goal is "a lightweight local cluster on NixOS," K3s is often easier operationally because it packages more of the control-plane complexity for you.
That is not a criticism of the NixOS module. It is just the practical distinction:
- use the built-in module when you want a more direct Kubernetes layout on NixOS
- use K3s when you want a smaller and easier local cluster
For learning or testing declarative NixOS service configuration, the built-in module is still valuable because everything is visible in one place.
Keep the Configuration Reproducible
One of the main advantages of NixOS is that the cluster configuration is declared in code. Take advantage of that:
- keep
configuration.nixunder version control - add
kubectland related tools explicitly toenvironment.systemPackages - avoid one-off manual changes that are not represented declaratively
If the cluster stops working after a later change, you can diff the Nix configuration rather than guessing what someone installed by hand weeks ago.
Common Pitfalls
The most common mistake is omitting masterAddress. The NixOS Kubernetes module expects it, and workers need a value they can actually resolve and reach.
Another frequent issue is forgetting to export KUBECONFIG to the cluster-admin kubeconfig generated by the module. kubectl then appears broken when the real problem is authentication context.
Networking is the next big source of pain. A node can boot with Kubernetes services running and still fail to join correctly because DNS, routing, or firewall rules are wrong.
Finally, do not choose a full Kubernetes deployment path when a lightweight local cluster would meet the need. On NixOS, that design choice matters as much as the individual options.
Summary
- NixOS can run Kubernetes declaratively through
services.kubernetes. - For a single-node dev cluster,
roles = [ "master" "node" ],masterAddress, andeasyCertsare the key starting options. - Rebuild with
nixos-rebuild switchand use the generated cluster-admin kubeconfig withkubectl. - For multi-node setups, workers use the
noderole and join withnixos-kubernetes-node-join. - Most setup failures come from address resolution, certificates, or firewall and networking issues rather than from NixOS itself.
Related reading
- Setup Kubernetes Pods via API Call using Go and Operator SDK
- Setup securityContext inside kubernetes deployment
- Share persistent volume claims amongst containers in Kubernetes/OpenShift
- Share storage/volume between worker nodes in Kubernetes?
- Sharing precompiled assets across docker containers
- Sharing resources between Terraform workspaces
- Shared dependencies with HELM
- Should dependencies between Helm charts reflect dependencies between microservices?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.