From 1ec89eec108de4ecfa8e3e7f7ff9016d05a24d59 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sun, 26 Apr 2026 19:30:54 +0000 Subject: [PATCH 1/5] feat(k3s): add k3s systemd service and kubeconfig management for kyber Manages k3s as a Nix-declared system service on kyber instead of requiring a manual curl install. Splits concerns across config/kube (kubeconfig) and services/k3s (systemd service). Co-Authored-By: Claude Opus 4.6 --- config/default.nix | 1 + config/kube/activate.sh | 26 ++++++++++++++++++++++++ config/kube/default.nix | 16 +++++++++++++++ home-manager/services/default.nix | 2 ++ home-manager/services/k3s/default.nix | 29 +++++++++++++++++++++++++++ home-manager/services/k3s/k3s.service | 25 +++++++++++++++++++++++ 6 files changed, 99 insertions(+) create mode 100644 config/kube/activate.sh create mode 100644 config/kube/default.nix create mode 100644 home-manager/services/k3s/default.nix create mode 100644 home-manager/services/k3s/k3s.service diff --git a/config/default.nix b/config/default.nix index b62912c24..00e4e1c7d 100644 --- a/config/default.nix +++ b/config/default.nix @@ -21,6 +21,7 @@ in ./hammerspoon ./jj ./k3s + ./kube ./karabiner ./llm ./mempalace diff --git a/config/kube/activate.sh b/config/kube/activate.sh new file mode 100644 index 000000000..07d77c213 --- /dev/null +++ b/config/kube/activate.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copy k3s kubeconfig to ~/.kube/config for non-root kubectl access +set -euo pipefail + +K3S_KUBECONFIG="/etc/rancher/k3s/k3s.yaml" +KUBE_DIR="$HOME/.kube" + +if [ ! -f "$K3S_KUBECONFIG" ]; then + exit 0 +fi + +SUDO_CMD="" +if command -v sudo >/dev/null 2>&1; then + SUDO_CMD="sudo" +elif [ -x /run/wrappers/bin/sudo ]; then + SUDO_CMD="/run/wrappers/bin/sudo" +elif [ -x /usr/bin/sudo ]; then + SUDO_CMD="/usr/bin/sudo" +fi + +if [ -n "$SUDO_CMD" ]; then + mkdir -p "$KUBE_DIR" + $SUDO_CMD cp "$K3S_KUBECONFIG" "$KUBE_DIR/config" + $SUDO_CMD chown "$(id -u):$(id -g)" "$KUBE_DIR/config" + chmod 600 "$KUBE_DIR/config" +fi diff --git a/config/kube/default.nix b/config/kube/default.nix new file mode 100644 index 000000000..fe236f0f3 --- /dev/null +++ b/config/kube/default.nix @@ -0,0 +1,16 @@ +{ + inputs, + lib, + pkgs, + ... +}: +let + inherit (inputs) host; +in +{ + home.activation.kube-config = lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) ( + lib.hm.dag.entryAfter [ "writeBoundary" ] '' + $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" + '' + ); +} diff --git a/home-manager/services/default.nix b/home-manager/services/default.nix index c7febbd75..c150251d2 100644 --- a/home-manager/services/default.nix +++ b/home-manager/services/default.nix @@ -16,6 +16,7 @@ let dockerPostgres = ./docker-postgres; dotfilesUpdater = import ./dotfiles-updater { inherit pkgs; }; gasTown = import ./gas-town { inherit pkgs; }; + k3s = ./k3s; keydApplicationMapper = ./keyd-application-mapper; makeUpdater = import ./make-updater { inherit pkgs; }; neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; }; @@ -38,6 +39,7 @@ in dockerPostgres dotfilesUpdater gasTown + k3s keydApplicationMapper makeUpdater neversslKeepalive diff --git a/home-manager/services/k3s/default.nix b/home-manager/services/k3s/default.nix new file mode 100644 index 000000000..a1f30c1e2 --- /dev/null +++ b/home-manager/services/k3s/default.nix @@ -0,0 +1,29 @@ +{ + lib, + pkgs, + inputs, + ... +}: +let + inherit (inputs) host; + + k3sServiceFile = pkgs.writeText "k3s.service" ( + builtins.readFile ( + pkgs.replaceVars ./k3s.service { + inherit (pkgs) coreutils; + k3s = pkgs.k3s; + } + ) + ); +in +lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) { + home.packages = [ pkgs.k3s ]; + + home.activation.setupK3s = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + if ! ${pkgs.diffutils}/bin/diff -q "${k3sServiceFile}" /etc/systemd/system/k3s.service >/dev/null 2>&1; then + $DRY_RUN_CMD sudo cp "${k3sServiceFile}" /etc/systemd/system/k3s.service + $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl daemon-reload + $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl enable --now k3s + fi + ''; +} diff --git a/home-manager/services/k3s/k3s.service b/home-manager/services/k3s/k3s.service new file mode 100644 index 000000000..50badb59e --- /dev/null +++ b/home-manager/services/k3s/k3s.service @@ -0,0 +1,25 @@ +[Unit] +Description=Lightweight Kubernetes +Documentation=https://k3s.io +Wants=network-online.target +After=network-online.target + +[Service] +Type=notify +EnvironmentFile=-/etc/default/%N +EnvironmentFile=-/etc/sysconfig/%N +KillMode=process +Delegate=yes +LimitNOFILE=1048576 +LimitNPROC=infinity +LimitCORE=infinity +TasksMax=infinity +TimeoutStartSec=0 +Restart=always +RestartSec=5s +ExecStartPre=-@coreutils@/bin/rm -f /run/k3s/containerd/containerd.sock +ExecStart=@k3s@/bin/k3s server +ExecStopPost=-@k3s@/bin/k3s-killall.sh + +[Install] +WantedBy=multi-user.target From c26750b610c8e682cd3832e2b96c913dfe37e0d2 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sun, 26 Apr 2026 19:33:02 +0000 Subject: [PATCH 2/5] refactor: move k3s.service template to config/k3s Co-Authored-By: Claude Opus 4.6 --- {home-manager/services => config}/k3s/k3s.service | 0 home-manager/services/k3s/default.nix | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {home-manager/services => config}/k3s/k3s.service (100%) diff --git a/home-manager/services/k3s/k3s.service b/config/k3s/k3s.service similarity index 100% rename from home-manager/services/k3s/k3s.service rename to config/k3s/k3s.service diff --git a/home-manager/services/k3s/default.nix b/home-manager/services/k3s/default.nix index a1f30c1e2..f3d2ef378 100644 --- a/home-manager/services/k3s/default.nix +++ b/home-manager/services/k3s/default.nix @@ -9,7 +9,7 @@ let k3sServiceFile = pkgs.writeText "k3s.service" ( builtins.readFile ( - pkgs.replaceVars ./k3s.service { + pkgs.replaceVars ../../config/k3s/k3s.service { inherit (pkgs) coreutils; k3s = pkgs.k3s; } From a164bc5760e910357439b3e39cb298a15e602531 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sun, 26 Apr 2026 19:34:14 +0000 Subject: [PATCH 3/5] refactor: move k3s service template rendering to config module Config module owns the replaceVars rendering and exposes the result via modules.k3s.serviceFile. Service module just consumes it. Co-Authored-By: Claude Opus 4.6 --- config/k3s/default.nix | 36 +++++++++++++++++++-------- home-manager/services/k3s/default.nix | 11 ++------ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/config/k3s/default.nix b/config/k3s/default.nix index 65e337e36..9fefc7e2a 100644 --- a/config/k3s/default.nix +++ b/config/k3s/default.nix @@ -5,16 +5,32 @@ ... }: { - # k3s config file stored in home directory - home.file.".config/k3s/config.yaml" = lib.mkIf pkgs.stdenv.isLinux { - source = ./config.yaml; - force = true; + options.modules.k3s.serviceFile = lib.mkOption { + type = lib.types.package; + default = pkgs.writeText "k3s.service" ( + builtins.readFile ( + pkgs.replaceVars ./k3s.service { + inherit (pkgs) coreutils; + k3s = pkgs.k3s; + } + ) + ); + readOnly = true; + description = "Rendered k3s systemd service file"; }; - # Activation script to sync config to /etc/rancher/k3s/ - home.activation.k3s-config = lib.mkIf pkgs.stdenv.isLinux ( - lib.hm.dag.entryAfter [ "writeBoundary" ] '' - $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" - '' - ); + config = { + # k3s config file stored in home directory + home.file.".config/k3s/config.yaml" = lib.mkIf pkgs.stdenv.isLinux { + source = ./config.yaml; + force = true; + }; + + # Activation script to sync config to /etc/rancher/k3s/ + home.activation.k3s-config = lib.mkIf pkgs.stdenv.isLinux ( + lib.hm.dag.entryAfter [ "writeBoundary" ] '' + $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" + '' + ); + }; } diff --git a/home-manager/services/k3s/default.nix b/home-manager/services/k3s/default.nix index f3d2ef378..4aadb73de 100644 --- a/home-manager/services/k3s/default.nix +++ b/home-manager/services/k3s/default.nix @@ -1,4 +1,5 @@ { + config, lib, pkgs, inputs, @@ -6,15 +7,7 @@ }: let inherit (inputs) host; - - k3sServiceFile = pkgs.writeText "k3s.service" ( - builtins.readFile ( - pkgs.replaceVars ../../config/k3s/k3s.service { - inherit (pkgs) coreutils; - k3s = pkgs.k3s; - } - ) - ); + k3sServiceFile = config.modules.k3s.serviceFile; in lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) { home.packages = [ pkgs.k3s ]; From 97d02975613f9d161af798f88dd3fdd5fb73145e Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sun, 26 Apr 2026 19:36:18 +0000 Subject: [PATCH 4/5] refactor: move k3s package to programs/k8s, render service in config - k3s package available on all Linux via programs/k8s - config/k3s renders k3s.service to ~/.config/k3s/ via home.file - services/k3s just reads the rendered file and installs it (kyber-only) Co-Authored-By: Claude Opus 4.6 --- config/k3s/default.nix | 39 ++++++++++----------------- home-manager/programs/k8s/default.nix | 25 ++++++++++------- home-manager/services/k3s/default.nix | 8 +++--- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/config/k3s/default.nix b/config/k3s/default.nix index 9fefc7e2a..1e06be319 100644 --- a/config/k3s/default.nix +++ b/config/k3s/default.nix @@ -1,36 +1,25 @@ { - config, lib, pkgs, ... }: { - options.modules.k3s.serviceFile = lib.mkOption { - type = lib.types.package; - default = pkgs.writeText "k3s.service" ( - builtins.readFile ( - pkgs.replaceVars ./k3s.service { - inherit (pkgs) coreutils; - k3s = pkgs.k3s; - } - ) - ); - readOnly = true; - description = "Rendered k3s systemd service file"; + home.file.".config/k3s/config.yaml" = lib.mkIf pkgs.stdenv.isLinux { + source = ./config.yaml; + force = true; }; - config = { - # k3s config file stored in home directory - home.file.".config/k3s/config.yaml" = lib.mkIf pkgs.stdenv.isLinux { - source = ./config.yaml; - force = true; + home.file.".config/k3s/k3s.service" = lib.mkIf pkgs.stdenv.isLinux { + source = pkgs.replaceVars ./k3s.service { + inherit (pkgs) coreutils; + k3s = pkgs.k3s; }; - - # Activation script to sync config to /etc/rancher/k3s/ - home.activation.k3s-config = lib.mkIf pkgs.stdenv.isLinux ( - lib.hm.dag.entryAfter [ "writeBoundary" ] '' - $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" - '' - ); + force = true; }; + + home.activation.k3s-config = lib.mkIf pkgs.stdenv.isLinux ( + lib.hm.dag.entryAfter [ "writeBoundary" ] '' + $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" + '' + ); } diff --git a/home-manager/programs/k8s/default.nix b/home-manager/programs/k8s/default.nix index 88f14adc8..613ced221 100644 --- a/home-manager/programs/k8s/default.nix +++ b/home-manager/programs/k8s/default.nix @@ -1,12 +1,17 @@ -{ pkgs, ... }: +{ lib, pkgs, ... }: { - home.packages = with pkgs; [ - k9s - kind - kubeconform - kubectl - kubectx - kubernetes-helm - kustomize - ]; + home.packages = + with pkgs; + [ + k9s + kind + kubeconform + kubectl + kubectx + kubernetes-helm + kustomize + ] + ++ lib.optionals stdenv.isLinux [ + k3s + ]; } diff --git a/home-manager/services/k3s/default.nix b/home-manager/services/k3s/default.nix index 4aadb73de..6170d55e2 100644 --- a/home-manager/services/k3s/default.nix +++ b/home-manager/services/k3s/default.nix @@ -7,14 +7,12 @@ }: let inherit (inputs) host; - k3sServiceFile = config.modules.k3s.serviceFile; + serviceFile = "${config.home.homeDirectory}/.config/k3s/k3s.service"; in lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) { - home.packages = [ pkgs.k3s ]; - home.activation.setupK3s = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - if ! ${pkgs.diffutils}/bin/diff -q "${k3sServiceFile}" /etc/systemd/system/k3s.service >/dev/null 2>&1; then - $DRY_RUN_CMD sudo cp "${k3sServiceFile}" /etc/systemd/system/k3s.service + if ! ${pkgs.diffutils}/bin/diff -q "${serviceFile}" /etc/systemd/system/k3s.service >/dev/null 2>&1; then + $DRY_RUN_CMD sudo cp "${serviceFile}" /etc/systemd/system/k3s.service $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl daemon-reload $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl enable --now k3s fi From 3d1b2349a9e853ebc77d2fdb3b743660bcdd4f60 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sun, 26 Apr 2026 19:37:50 +0000 Subject: [PATCH 5/5] refactor: move kubeconfig copy into k3s service, remove config/kube The kubeconfig depends on k3s running, so it belongs in the service activation alongside the systemd setup. Co-Authored-By: Claude Opus 4.6 --- config/default.nix | 1 - config/kube/activate.sh | 26 -------------------------- config/kube/default.nix | 16 ---------------- home-manager/services/k3s/default.nix | 9 +++++++++ 4 files changed, 9 insertions(+), 43 deletions(-) delete mode 100644 config/kube/activate.sh delete mode 100644 config/kube/default.nix diff --git a/config/default.nix b/config/default.nix index 00e4e1c7d..b62912c24 100644 --- a/config/default.nix +++ b/config/default.nix @@ -21,7 +21,6 @@ in ./hammerspoon ./jj ./k3s - ./kube ./karabiner ./llm ./mempalace diff --git a/config/kube/activate.sh b/config/kube/activate.sh deleted file mode 100644 index 07d77c213..000000000 --- a/config/kube/activate.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# Copy k3s kubeconfig to ~/.kube/config for non-root kubectl access -set -euo pipefail - -K3S_KUBECONFIG="/etc/rancher/k3s/k3s.yaml" -KUBE_DIR="$HOME/.kube" - -if [ ! -f "$K3S_KUBECONFIG" ]; then - exit 0 -fi - -SUDO_CMD="" -if command -v sudo >/dev/null 2>&1; then - SUDO_CMD="sudo" -elif [ -x /run/wrappers/bin/sudo ]; then - SUDO_CMD="/run/wrappers/bin/sudo" -elif [ -x /usr/bin/sudo ]; then - SUDO_CMD="/usr/bin/sudo" -fi - -if [ -n "$SUDO_CMD" ]; then - mkdir -p "$KUBE_DIR" - $SUDO_CMD cp "$K3S_KUBECONFIG" "$KUBE_DIR/config" - $SUDO_CMD chown "$(id -u):$(id -g)" "$KUBE_DIR/config" - chmod 600 "$KUBE_DIR/config" -fi diff --git a/config/kube/default.nix b/config/kube/default.nix deleted file mode 100644 index fe236f0f3..000000000 --- a/config/kube/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - inputs, - lib, - pkgs, - ... -}: -let - inherit (inputs) host; -in -{ - home.activation.kube-config = lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) ( - lib.hm.dag.entryAfter [ "writeBoundary" ] '' - $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" - '' - ); -} diff --git a/home-manager/services/k3s/default.nix b/home-manager/services/k3s/default.nix index 6170d55e2..0a4919121 100644 --- a/home-manager/services/k3s/default.nix +++ b/home-manager/services/k3s/default.nix @@ -16,5 +16,14 @@ lib.mkIf (pkgs.stdenv.isLinux && host.isKyber) { $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl daemon-reload $DRY_RUN_CMD sudo ${pkgs.systemd}/bin/systemctl enable --now k3s fi + + K3S_KUBECONFIG="/etc/rancher/k3s/k3s.yaml" + KUBE_DIR="${config.home.homeDirectory}/.kube" + if [ -f "$K3S_KUBECONFIG" ]; then + $DRY_RUN_CMD mkdir -p "$KUBE_DIR" + $DRY_RUN_CMD sudo cp "$K3S_KUBECONFIG" "$KUBE_DIR/config" + $DRY_RUN_CMD sudo chown "$(id -u):$(id -g)" "$KUBE_DIR/config" + $DRY_RUN_CMD chmod 600 "$KUBE_DIR/config" + fi ''; }