fix(k3s): authorize galactica on kyber and surface client sync failures

Merged
SH
6mo ago
+164-15

Summary

Two bugs prevented kubectl from working on galactica after make switch:

  1. Silent client failure. config/k3s/activate-client.sh discarded scp stderr (2>/dev/null) and used if scp; then ...; fi with no else branch. Any sync failure left ~/.kube/config-kyber absent while activation looked clean.
  2. Server never authorized galactica. The scp succeeded as a design only on the assumption that galactica's pubkey was already in kyber's ~/.ssh/authorized_keys. Nothing in the repo put it there, so a fresh sync always hit Permission denied (publickey).

While fixing #2 the galactica/kyber/matic pubkeys turned out to be hardcoded in three secrets.nix files, so they got pulled into a single shared module.

Changes

  • named-hosts/pubkeys.nix (new): single source of truth for the three host pubkeys.
  • named-hosts/{galactica,kyber,matic}/secrets.nix: inherit from pubkeys.nix instead of duplicating the strings.
  • config/k3s/default.nix: read galactica's pubkey from pubkeys.nix and template it into activate.sh via pkgs.replaceVars (matching the existing k3s.service pattern).
  • config/k3s/activate.sh: new ensure_authorized_key helper appends galactica's key to kyber's ~/.ssh/authorized_keys idempotently, with a placeholder guard so the unsubstituted @galacticaAuthorizedKey@ template is a no-op.
  • config/k3s/activate-client.sh: capture scp stderr to a temp file, log a one-line success on the happy path, on failure print k3s-client: failed to fetch kubeconfig from ... plus the indented scp output. Still exits 0 so a not-yet-authorized fresh machine does not break home-manager activation.
  • Specs:
    • spec/activate_k3s_spec.sh (+10 examples): placeholder declared, helper exists, fixed-string match used, idempotency, happy-path append, preserve-existing, no-op on unsubstituted placeholder.
    • spec/activate_k3s_client_spec.sh (+2 examples): reject 2>/dev/null, require failure-log string.

Test plan

  • nix flake check --no-build (galactica, runner, default eval clean)
  • shellspec spec/activate_k3s_spec.sh spec/activate_k3s_client_spec.sh -> 25 examples, 0 failures
  • shellcheck clean on both activate scripts
  • Reran the client script on galactica - new logging surfaced the underlying Permission denied (publickey) instead of vanishing
  • On kyber: make build && make switch, confirm a single k3s-server: authorized galactica SSH key for kubeconfig sync line and that ~/.ssh/authorized_keys contains galactica's pubkey exactly once after multiple runs
  • On galactica: make switch, confirm k3s-client: kubeconfig synced from kyber.tail950b36.ts.net and kubectl get nodes succeeds