Ik heb geschreven over Talos Linux als het immutable Kubernetes OS, en ik heb Arch vs NixOS voor werkstations vergeleken. Na beide blijft er één vraag in mijn inbox landen: wat dacht je van NixOS voor de Kubernetes nodes zelf?
Een terechte vraag, want op papier lijken deze twee broers en zussen. NixOS en Talos zijn allebei declaratief. Beide kunnen immutable zijn. Beide zetten hun configuratie onder versiebeheer. Dus waarom zou je de ene boven de andere kiezen om een cluster te draaien?
Eerst mijn bias, zodat je de rest met die kennis leest: ik draai een soevereine homelab waar ik elke laag wil begrijpen en bezitten, en ik heb een lage tolerantie voor drift. Ik heb beide in productie gehad. Deze post is mij die twee eerlijk vergelijken, geen winnaar kronen.
Ik vergelijk ze op de criteria die de beslissing echt sturen: configuratiemodel, security posture, flexibiliteit, upgrades, Kubernetes-integratie, en hoe je ze debugt als het misgaat. Feature-lijstjes vind je wel op de homepage van beide projecten. De trade-offs zijn waar de echte keuze zit.
Het filosofische verschil
Begin bij de intentie, want die kleurt al het andere.
Talos Linux is een single-purpose besturingssysteem. Het bestaat om Kubernetes te draaien en niets anders. Elke designbeslissing buigt naar dat ene doel.
NixOS is een general-purpose besturingssysteem dat toevallig erg goed is in Kubernetes draaien. Het kan alles wat een traditionele Linux kan, alleen wordt de hele machine als declaratieve configuratie beschreven.
Dat gat in intentie is de wortel van elke trade-off hieronder. Houd het in je hoofd terwijl we verder gaan.
Configuratie modellen
Talos: YAML all the way
Talos configuratie is platte YAML:
machine:
type: controlplane
network:
hostname: node-01
interfaces:
- interface: eth0
dhcp: true
install:
disk: /dev/sda
cluster:
clusterName: production
controlPlane:
endpoint: https://k8s.example.com:6443
Je past het toe met talosctl apply-config, en de node convergeert naar die staat. Voorspelbaar, geen verrassingen.
NixOS: de Nix taal
NixOS configuratie is geschreven in Nix, een functionele taal:
{ config, pkgs, ... }:
{
networking.hostName = "node-01";
services.k3s = {
enable = true;
role = "server";
extraFlags = toString [
"--cluster-init"
"--disable traefik"
];
};
# Je kunt hier alles doen
services.prometheus.exporters.node.enable = true;
virtualisation.docker.enable = true;
system.stateVersion = "24.05";
}
Je past het toe met nixos-rebuild switch, en het systeem convergeert naar de gedeclareerde staat.
De trade-off
Talos’s YAML is beperkt, en je leert het in een middag. De Nix taal is veel krachtiger, en het kost je weken voordat het ophoudt vreemd te voelen. Dat zeg ik als iemand die Nix mag.
De keuze gaat dus over scope. Heb je alleen Kubernetes nodig? Dan wint Talos’s eenvoud meteen. Heb je Kubernetes plus een stapel andere dingen op dezelfde machine nodig? Dan koopt die Nix leercurve je iets echts.
Security posture
Talos: veilig door verwijdering
Talos verdient zijn security door attack surface te schrappen:
- Geen SSH daemon
- Geen shell
- Geen package manager
- Read-only root filesystem
- Minimale userspace (alleen containerd, kubelet en essentials)
Een aanvaller die een container compromitteert en ontsnapt naar de host vindt vrijwel niets bruikbaars. Er zijn geen tools om mee te pivoten, geen voor de hand liggend persistence mechanisme, geen package manager om malware mee binnen te halen. Dat sluit direct aan op een waarde waar ik om geef: de blast radius verkleinen wanneer (niet als) er iets gecompromitteerd raakt.
NixOS: veilig door configuratie
NixOS kan een heel eind gehardend worden, maar je kiest er actief voor:
{
# Disable SSH password auth
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
};
# Firewall
networking.firewall = {
enable = true;
allowedTCPPorts = [ 6443 ];
};
# Read-only store (altijd waar)
# Maar /etc, /var, /home zijn nog steeds mutable
}
De /nix/store is altijd read-only, wat geweldig is. De rest van het filesystem blijft standaard mutable. Je kunt het verder dichttimmeren, maar dat is extra werk dat je moet onthouden te doen.
De trade-off
Talos is out of the box gehardend. NixOS komt daar ook, maar alleen als je er bewust moeite in steekt. Voor nodes die alleen Kubernetes draaien zijn Talos’s paranoïde defaults meestal precies wat je wilt, en de discipline is niet optioneel, wat het punt is.
Flexibiliteit vs focus
Hier trekken de twee systemen het hardst uit elkaar.
Wat NixOS kan dat Talos niet kan
Op een NixOS node kan je Kubernetes machine ook draaien:
- Systeem services: Prometheus node exporter, log shippers, monitoring agents, allemaal als systemd services in plaats van pods
- Non-containerized workloads: soms heb je echt een bare-metal database of een legacy app nodig naast Kubernetes
- Custom tooling: installeer elk pakket uit nixpkgs (80.000+ ervan)
- Development tools: als je op de node zelf moet debuggen, zijn de tools een configregel ver weg
Hier draait een lokale PostgreSQL naast Kubernetes voor testing:
{
services.k3s.enable = true;
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
};
}
Wat Talos doet dat NixOS niet wil
Talos’s restricties zijn het hele product:
- Geen drift: je kunt letterlijk geen ongedocumenteerde wijziging maken
- Gedwongen discipline: elke wijziging gaat via config, dan API, dan apply
- Simpeler mentaal model: de node is de config, punt
- Kleiner attack surface: wat niet bestaat kan niet geëxploiteerd worden
De trade-off
Als je nodes alleen Kubernetes workloads draaien, houden Talos’s muren je tegen om fouten te maken. Als je nodes meer moeten doen, worden diezelfde muren een kooi en is NixOS’s flexibiliteit het antwoord.
Upgrade en rollback
Talos: transactionele OS updates
talosctl upgrade --nodes 192.168.1.10 \
--image ghcr.io/siderolabs/installer:v1.7.0
Talos schrijft het nieuwe OS naar een alternatieve partitie en reboot. Als de nieuwe image niet boot, rolt het automatisch terug naar de vorige versie. De upgrade is atomic, slaagt volledig of faalt volledig, met niets ertussen om te babysitten.
NixOS: generation-based rollback
nixos-rebuild switch --flake .#node-01
NixOS creëert een nieuwe “generation” voor elke configuratiewijziging. Elke generation is bootbaar vanuit GRUB. Rollback is een eerdere selecteren:
nixos-rebuild switch --rollback
# Of selecteer vanuit boot menu
NixOS bewaart standaard meerdere generations, dus je kunt terugvallen naar een configuratie van weken geleden.
De trade-off
Beide rollback verhalen zijn echt goed, wat zeldzamer is dan het klinkt. Talos is meer automatisch: een gefaalde boot triggert de rollback voor je. NixOS is flexibeler: je bewaart willekeurige generations en kunt teruggaan naar welke je maar wilt.
Kubernetes integratie
Talos: gebouwd voor Kubernetes
Talos komt met alles wat een cluster nodig heeft:
- Kubernetes componenten zijn ingebouwd
- CNI configuratie leeft in de machine config
- etcd management wordt voor je afgehandeld
- Certificate rotation is automatisch
- Upgrades coördineren met Kubernetes (drain, upgrade, uncordon)
Je installeert Kubernetes niet op Talos. Kubernetes is onderdeel van Talos.
NixOS: Kubernetes als service
NixOS geeft je meerdere opties:
# Optie 1: K3s (lichtgewicht)
services.k3s = {
enable = true;
role = "server";
};
# Optie 2: Volledige Kubernetes via kubeadm
services.kubernetes = {
roles = ["master" "node"];
masterAddress = "k8s.example.com";
};
# Optie 3: Alleen de kubelet
services.kubernetes.kubelet.enable = true;
Jij bepaalt hoe Kubernetes gedeployed wordt. Meer opties, maar ook meer beslissingen die jij bezit.
De trade-off
Talos’s opinionated integratie betekent minder beslissingen en verstandige defaults specifiek voor Kubernetes. NixOS laat je Kubernetes bedraden zoals jou uitkomt, ten koste van het zelf moeten maken van die keuzes en erachter staan.
Debugging en troubleshooting
Talos: API-only access
# Logs bekijken
talosctl logs kubelet --nodes 192.168.1.10
# Systeem info ophalen
talosctl get members
# Bestanden lezen
talosctl read /etc/hosts
# Dashboard (read-only TUI)
talosctl dashboard
Alles gaat via de API. Geen SSH, geen shell. Er is een debug container feature voor noodgevallen, en die is opzettelijk onhandig zodat je er niet achteloos naar grijpt.
NixOS: volledige Linux access
# SSH erin
ssh root@192.168.1.10
# Gebruik elke tool
htop
journalctl -u k3s
kubectl get nodes
vim /etc/nixos/configuration.nix
Het is een volledige Linux machine. Elke tool die je kent werkt al. Comfortabel, en stilletjes gevaarlijk, want elke SSH sessie is een kans om een wijziging te maken die nooit terug naar Git komt.
De trade-off
Talos duwt je om te debuggen via juiste kanalen: API, logs, metrics. NixOS laat je debuggen hoe je wilt, inclusief de manieren die stilletjes drift introduceren. Of die vrijheid een geschenk of een valstrik is hangt volledig van je discipline af.
Mijn aanbeveling
Na beide gedraaid te hebben, is dit het beslisframework dat ik echt gebruik.
Kies Talos wanneer:
- Kubernetes de enige workload is op deze nodes
- Security paramount is en je minimaal attack surface wilt
- Je guardrails wilt en drift voorkomen belangrijker is dan flexibiliteit
- Je comfortabel bent met API-driven management
- Je team gedisciplineerd is in declaratieve workflows
Kies NixOS wanneer:
- Je non-Kubernetes workloads nodig hebt op dezelfde nodes
- Je volledige Linux flexibiliteit wilt met declaratieve voordelen
- Je specifieke packages nodig hebt die niet beschikbaar zijn als Talos extensions
- Je team al geïnvesteerd is in het Nix ecosysteem
- Je diep wilt customizen voorbij wat Talos toestaat
Mijn setup
Ik draai beide, in verschillende rollen:
- Homelab Kubernetes: Talos. Deze nodes draaien alleen Kubernetes, en ik wil de security en de eenvoud die komen met een cluster dat zich nergens kan verstoppen.
- Homelab auxiliary servers: NixOS. Deze draaien Postgres, backup services en monitoring infrastructuur die ik bewust buiten Kubernetes houd.
De combinatie geeft me locked-down cluster nodes die fysiek niet kunnen driften, plus flexibele NixOS machines voor alles wat niet in een pod thuishoort. Elke tool zit waar zijn beperkingen helpen in plaats van pijn doen.
De hybride aanpak
Sommige teams draaien NixOS voor control plane nodes, waar ze meer debugging access willen, en Talos voor workers, waar ze maximale lockdown willen. Het werkt, al voegt het operationeel oppervlak toe dat je nu in twee vormen moet onderhouden.
Er is nog een pad dat ik goed heb zien werken: begin op NixOS omdat het bekend is, migreer dan naar Talos als je team volwassener wordt in declaratieve operations. NixOS leert het mentale model zacht aan. Talos enforced het of je het nu leuk vindt of niet.
De KubeVirt optie: Kubernetes als control plane voor alles
Er is een derde aanpak die het verdient op tafel te leggen: KubeVirt gebruiken om NixOS als VMs binnen Kubernetes te draaien. Dit draait de framing om. In plaats van NixOS of Talos voor je nodes te kiezen, draai je Talos (of een ander minimaal OS) op de bare metal en draai je je NixOS workloads als VMs die Kubernetes beheert.
De stack ziet er zo uit:
flowchart TD
subgraph stack["KubeVirt Stack"]
ArgoCD["ArgoCD (GitOps)"]
KubeVirt["KubeVirt VMs (NixOS, andere OSes)"]
K8s["Kubernetes (K3s/Talos)"]
BareMetal["Bare Metal (Ansible provisioned)"]
ArgoCD --> KubeVirt
KubeVirt --> K8s
K8s --> BareMetal
end
Waarom dit werkt
Je VM definities worden Kubernetes manifests:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: nixos-workload-01
spec:
running: true
template:
spec:
domain:
resources:
requests:
memory: 4Gi
cpu: 2
devices:
disks:
- name: nixos-disk
disk:
bus: virtio
volumes:
- name: nixos-disk
persistentVolumeClaim:
claimName: nixos-workload-01-pvc
Met ArgoCD aan het stuur leeft deze VM definitie in Git. De NixOS config binnen de VM leeft ook in Git. Het geheel is declaratief, auditeerbaar en version-controlled van boven tot onder.
De volledig declaratieve stack
Combineer dat met:
- Ansible voor bare metal provisioning (installeer Talos of K3s op de fysieke nodes)
- ArgoCD voor het beheren van alles in Kubernetes, KubeVirt VMs inbegrepen
- NixOS flakes voor VM configuraties, gepulled vanuit Git tijdens VM boot
De opbrengst: je hele infrastructuur, van bare metal tot VMs tot Kubernetes workloads, is gedefinieerd in Git. Wijzig een VM’s NixOS config, commit, ArgoCD synct, de VM herbouwt. Volledige audit trail, volledige reproduceerbaarheid, precies het soevereiniteitsverhaal waar ik steeds op terugkom.
Wanneer dit zinvol is
Deze aanpak verdient zijn complexiteit wanneer:
- Je gemixte workloads nodig hebt, sommige gecontaineriseerd, sommige die echt volledige VMs vereisen
- Je één control plane (Kubernetes) wilt voor het geheel
- Je workloads hebt die niet gecontaineriseerd kunnen worden maar die je toch onder GitOps wilt
- Je al KubeVirt draait om andere redenen
De kost is reëel: je draait nu een virtualisatielaag binnen Kubernetes, met alles wat dat impliceert. Maar als je VMs toch nodig hebt, is ze declaratief beheren via dezelfde GitOps pipeline als de rest van je estate een echt sterke positie om in te zitten.
Voorbeeld: database op NixOS VM
Stel je wilt een PostgreSQL server met specifieke kernel tuning die niet in een container past. In plaats van een aparte NixOS server met de hand te onderhouden:
- Definieer de VM in een KubeVirt manifest (in Git)
- De VM boot NixOS en haalt zijn config op vanuit een flake (in Git)
- ArgoCD beheert de VM lifecycle
- Backups, monitoring, networking lopen allemaal via Kubernetes
De database krijgt NixOS’s flexibiliteit. Jij krijgt Kubernetes’s orchestration. Alles blijft in Git.
Conclusie
NixOS en Talos wijzen allebei naar dezelfde toekomst: declaratieve, reproduceerbare, version-controlled infrastructuur. De keuze tussen hen ging nooit over welke objectief “beter” is. Het gaat over welke set constraints dient wat je probeert te bouwen.
Talos zet je vast in Kubernetes-only, API-only, minimal-surface operations. Die muren zijn een feature als je een secure, drift-free Kubernetes platform wilt en je liever hebt dat het systeem de discipline enforced dan dat je op de jouwe leunt.
NixOS houdt je aan declaratieve configuratie terwijl je de volle loop van een Linux machine behoudt. Die constraints zijn een feature als je dat bereik nodig hebt en je je team vertrouwt het te gebruiken zonder in drift te glijden.
De echte vraag is dus niet “NixOS of Talos?” Het is “welke constraints wil ik eigenlijk mijn gedrag laten enforcen?” Voor pure Kubernetes nodes neig ik naar Talos. Voor alles eromheen neig ik naar NixOS. Steeds meer denk ik dat het eerlijke antwoord beide is, elk gehouden in de rol waar zijn grenzen je een dienst bewijzen.
Beide communities zijn uitstekend, en beide systemen zijn in actieve ontwikkeling. Je kunt eigenlijk met geen van beide verkeerd kiezen. Declaratief denken over je infrastructuur zet je al voor op de meesten.
