From 346ad3665d9bd81a00e2c550d0cb718c610f67d0 Mon Sep 17 00:00:00 2001 From: John Ogle Date: Sat, 10 Jan 2026 20:08:57 -0800 Subject: [PATCH] feat(k3s-node): Add k3s-node role and enable on john-endesktop Add reusable k3s-node role with configurable options for server/agent modes. Configure john-endesktop as a k3s agent joining the cluster at 10.0.0.222. Role supports: - Server or agent role selection - Configurable server address and token file - Graceful node shutdown - Optional firewall port opening - Cluster initialization for first server Note: NixOS nodes must be labeled with `k3s-upgrade=disabled` to exclude them from the system-upgrade-controller, since NixOS manages k3s upgrades through Nix rather than in-place binary replacement. --- machines/john-endesktop/configuration.nix | 8 +++ roles/default.nix | 1 + roles/k3s-node/default.nix | 81 +++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 roles/k3s-node/default.nix diff --git a/machines/john-endesktop/configuration.nix b/machines/john-endesktop/configuration.nix index a3a61c5..ec20935 100644 --- a/machines/john-endesktop/configuration.nix +++ b/machines/john-endesktop/configuration.nix @@ -104,6 +104,14 @@ with lib; # User configuration roles.users.enable = true; + # k3s agent configuration + roles.k3s-node = { + enable = true; + role = "agent"; + # serverAddr defaults to https://10.0.0.222:6443 + # tokenFile defaults to /etc/k3s/token + }; + # Time zone time.timeZone = "America/Los_Angeles"; # Adjust as needed diff --git a/roles/default.nix b/roles/default.nix index ceddcc7..a56fd02 100644 --- a/roles/default.nix +++ b/roles/default.nix @@ -9,6 +9,7 @@ with lib; ./bluetooth ./btrfs ./desktop + ./k3s-node ./kodi ./nfs-mounts ./nvidia diff --git a/roles/k3s-node/default.nix b/roles/k3s-node/default.nix new file mode 100644 index 0000000..17123a2 --- /dev/null +++ b/roles/k3s-node/default.nix @@ -0,0 +1,81 @@ +{ lib, config, pkgs, ... }: + +with lib; + +let + cfg = config.roles.k3s-node; +in +{ + options.roles.k3s-node = { + enable = mkEnableOption "Enable k3s node"; + + role = mkOption { + type = types.enum [ "server" "agent" ]; + default = "agent"; + description = "k3s role: server (control plane) or agent (worker)"; + }; + + serverAddr = mkOption { + type = types.str; + default = "https://10.0.0.222:6443"; + description = "URL of k3s server to join (required for agents, used for HA servers)"; + }; + + tokenFile = mkOption { + type = types.path; + default = "/etc/k3s/token"; + description = "Path to file containing the cluster join token"; + }; + + clusterInit = mkOption { + type = types.bool; + default = false; + description = "Initialize a new cluster (first server only)"; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + description = "Additional flags to pass to k3s"; + }; + + gracefulNodeShutdown = mkOption { + type = types.bool; + default = true; + description = "Enable graceful node shutdown"; + }; + + openFirewall = mkOption { + type = types.bool; + default = true; + description = "Open firewall ports for k3s"; + }; + }; + + config = mkIf cfg.enable { + # k3s service configuration + services.k3s = { + enable = true; + role = cfg.role; + tokenFile = cfg.tokenFile; + extraFlags = cfg.extraFlags; + gracefulNodeShutdown.enable = cfg.gracefulNodeShutdown; + serverAddr = if (cfg.role == "agent" || !cfg.clusterInit) then cfg.serverAddr else ""; + clusterInit = cfg.role == "server" && cfg.clusterInit; + }; + + # Firewall rules for k3s + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ + 6443 # k3s API server + 10250 # kubelet metrics + ] ++ optionals (cfg.role == "server") [ + 2379 # etcd clients (HA) + 2380 # etcd peers (HA) + ]; + allowedUDPPorts = [ + 8472 # flannel VXLAN + ]; + }; + }; +}