{ config, lib, pkgs, ... }: let pinnedK8s = lib.attrByPath [ "kubernetes_1_31" ] pkgs.kubernetes pkgs; kubeVipImage = "ghcr.io/kube-vip/kube-vip:v0.8.9"; in { options.terrahome.kubeadm = { k8sMinor = lib.mkOption { type = lib.types.str; default = "1.31"; }; controlPlaneInterface = lib.mkOption { type = lib.types.str; default = "eth0"; }; controlPlaneVipSuffix = lib.mkOption { type = lib.types.int; default = 250; }; podSubnet = lib.mkOption { type = lib.types.str; default = "10.244.0.0/16"; }; serviceSubnet = lib.mkOption { type = lib.types.str; default = "10.96.0.0/12"; }; clusterDomain = lib.mkOption { type = lib.types.str; default = "cluster.local"; }; }; config = { boot.kernelModules = [ "overlay" "br_netfilter" ]; boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; "net.bridge.bridge-nf-call-iptables" = 1; "net.bridge.bridge-nf-call-ip6tables" = 1; }; virtualisation.containerd.enable = true; virtualisation.containerd.settings = { plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options.SystemdCgroup = true; }; swapDevices = lib.mkForce [ ]; services.openssh.enable = true; services.openssh.settings = { PasswordAuthentication = false; KbdInteractiveAuthentication = false; }; users.users.micqdf = { isNormalUser = true; extraGroups = [ "wheel" ]; }; security.sudo.wheelNeedsPassword = false; nix.settings.trusted-users = [ "root" "micqdf" ]; nix.gc = { automatic = true; dates = "daily"; options = "--delete-older-than 3d"; }; nix.settings.auto-optimise-store = true; environment.variables = { KUBECONFIG = "/etc/kubernetes/admin.conf"; KUBE_VIP_IMAGE = kubeVipImage; }; environment.systemPackages = (with pkgs; [ containerd cri-tools cni-plugins pinnedK8s kubernetes-helm conntrack-tools socat ethtool ipvsadm iproute2 iptables ebtables jq curl vim gawk ]) ++ [ (pkgs.writeShellScriptBin "th-kubeadm-init" '' set -euo pipefail iface="${config.terrahome.kubeadm.controlPlaneInterface}" if ! ip link show "$iface" >/dev/null 2>&1; then iface="$(ip -o -4 route show to default | awk 'NR==1 {print $5}')" fi if [ -z "''${iface:-}" ]; then echo "Could not determine network interface for kube-vip" exit 1 fi suffix="${toString config.terrahome.kubeadm.controlPlaneVipSuffix}" pod_subnet="${config.terrahome.kubeadm.podSubnet}" service_subnet="${config.terrahome.kubeadm.serviceSubnet}" domain="${config.terrahome.kubeadm.clusterDomain}" local_ip_cidr=$(ip -4 -o addr show dev "$iface" | awk 'NR==1 {print $4}') if [ -z "''${local_ip_cidr:-}" ]; then echo "Could not determine IPv4 CIDR on interface $iface" exit 1 fi subnet_prefix=$(echo "$local_ip_cidr" | cut -d/ -f1 | awk -F. '{print $1"."$2"."$3}') vip="$subnet_prefix.$suffix" echo "Using control-plane endpoint: $vip:6443" echo "Using kube-vip interface: $iface" mkdir -p /etc/kubernetes/manifests ctr image pull "$KUBE_VIP_IMAGE" ctr run --rm --net-host "$KUBE_VIP_IMAGE" kube-vip /kube-vip manifest pod \ --interface "$iface" \ --address "$vip" \ --controlplane \ --services \ --arp \ --leaderElection \ > /etc/kubernetes/manifests/kube-vip.yaml kubeadm init \ --control-plane-endpoint "$vip:6443" \ --upload-certs \ --pod-network-cidr "$pod_subnet" \ --service-cidr "$service_subnet" \ --service-dns-domain "$domain" mkdir -p /root/.kube cp /etc/kubernetes/admin.conf /root/.kube/config chmod 600 /root/.kube/config echo echo "Next: install Cilium, then generate join commands:" echo " kubeadm token create --print-join-command" echo " kubeadm token create --print-join-command --certificate-key " '') (pkgs.writeShellScriptBin "th-kubeadm-join-control-plane" '' set -euo pipefail if [ "$#" -lt 1 ]; then echo "Usage: th-kubeadm-join-control-plane ''" exit 1 fi iface="${config.terrahome.kubeadm.controlPlaneInterface}" if ! ip link show "$iface" >/dev/null 2>&1; then iface="$(ip -o -4 route show to default | awk 'NR==1 {print $5}')" fi if [ -z "''${iface:-}" ]; then echo "Could not determine network interface for kube-vip" exit 1 fi suffix="${toString config.terrahome.kubeadm.controlPlaneVipSuffix}" local_ip_cidr=$(ip -4 -o addr show dev "$iface" | awk 'NR==1 {print $4}') if [ -z "''${local_ip_cidr:-}" ]; then echo "Could not determine IPv4 CIDR on interface $iface" exit 1 fi subnet_prefix=$(echo "$local_ip_cidr" | cut -d/ -f1 | awk -F. '{print $1"."$2"."$3}') vip="$subnet_prefix.$suffix" mkdir -p /etc/kubernetes/manifests ctr image pull "$KUBE_VIP_IMAGE" ctr run --rm --net-host "$KUBE_VIP_IMAGE" kube-vip /kube-vip manifest pod \ --interface "$iface" \ --address "$vip" \ --controlplane \ --services \ --arp \ --leaderElection \ > /etc/kubernetes/manifests/kube-vip.yaml eval "$1" '') (pkgs.writeShellScriptBin "th-kubeadm-join-worker" '' set -euo pipefail if [ "$#" -lt 1 ]; then echo "Usage: th-kubeadm-join-worker ''" exit 1 fi eval "$1" '') (pkgs.writeShellScriptBin "th-kubeadm-status" '' set -euo pipefail systemctl is-active containerd || true systemctl is-active kubelet || true crictl info >/dev/null && echo "crictl: ok" || echo "crictl: not-ready" '') ]; systemd.services.kubelet = { description = "Kubernetes Kubelet"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "containerd.service" "network-online.target" ]; serviceConfig = { ExecStart = "${pinnedK8s}/bin/kubelet"; Restart = "always"; RestartSec = "10"; }; }; systemd.tmpfiles.rules = [ "d /etc/kubernetes 0755 root root -" "d /etc/kubernetes/manifests 0755 root root -" ]; }; }