feat(ssh): full homelab alias set on the Mac + separate interactive key

config/ssh_homelab now carries the curated alias set from ~/bin/CLAUDE.md
(pve nodes, machines, key CTs, switch, tailscale hosts). Interactive auth
uses a NEW key, id_ed25519_homelab, because the existing id_ed25519 is
rrsync-jailed on pve173 and sshd honours the first matching authorized_keys
line per key — one key can't be both a jail and a shell there.

- setup.sh generates id_ed25519_homelab (idempotent)
- backup.sh pins the jailed key: -o IdentitiesOnly=yes -i $HOME/.ssh/id_ed25519
- scripts/authorize-mac-key.sh (run on steel141) appends the pubkey on every
  LAN host via claude's aliases; wired into run.sh
- bedroom alias: seth -> root (matches steel141; was undocumented)

Verified from the Mac: 12 aliases land as the right user@host; the backup key
is refused a shell by rrsync (checked with id — rrsync whitelists true);
backup.sh still runs. Offline at push time: bedroom thinkcentre seth-pi
pinail openclaw2 — re-run authorize-mac-key.sh when they're up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mortdecai
2026-09-15 20:31:25 -04:00
parent 43877eb78f
commit 2028508cb9
7 changed files with 82 additions and 4 deletions
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# From steel141: put the Mac's interactive pubkey on every LAN host in config/ssh_homelab, via
# claude's own aliases (same names, same target users). Idempotent; called by run.sh, safe alone.
# steel141 itself is the one exception: seth's authorized_keys needs sudo from the claude account.
set -euo pipefail
PUB=$(ssh -o BatchMode=yes mac cat .ssh/id_ed25519_homelab.pub)
[[ $PUB == ssh-ed25519\ AAAA* ]] || { echo "no ~/.ssh/id_ed25519_homelab on the Mac — run setup.sh first"; exit 1; }
ADD='umask 077; mkdir -p ~/.ssh; if grep -qF "$PUB" ~/.ssh/authorized_keys 2>/dev/null; then echo "[skip] $H"; else echo "$PUB" >> ~/.ssh/authorized_keys; echo "[set] $H"; fi'
for H in pve112 pve173 pve197 pve241 bedroom vdj-rig thinkcentre seth-pi pinail caddy openclaw2 rtorrent emby mcsmanager pihole arr; do
ssh -o BatchMode=yes -o ConnectTimeout=5 "$H" "PUB='$PUB' H=$H bash -s" <<<"$ADD" || echo "[FAIL] $H"
done
sudo -n -u seth env PUB="$PUB" H=steel141 bash -c "$ADD"
+3 -1
View File
@@ -7,4 +7,6 @@ src=()
for d in "$HOME/Music/Ableton" "$HOME/Documents"; do [[ -d $d ]] && src+=("$d"); done
[[ ${#src[@]} -gt 0 ]] || { echo "nothing to back up yet"; exit 0; }
# Remote path is relative to the rrsync root (/tank/backups/mac) set in root's authorized_keys on pve173.
exec /opt/homebrew/bin/rsync -a --delete -e 'ssh -o BatchMode=yes' "${src[@]}" root@192.168.0.173:/
# -i pins the jailed key; the Host * default (id_ed25519_homelab) has a root shell on pve173 and must NOT be offered first.
# Check the jail holds: ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 root@192.168.0.173 id -> "rrsync error: ... does not run rsync" (NOT `true`: rrsync whitelists it as a ping).
exec /opt/homebrew/bin/rsync -a --delete -e "ssh -o BatchMode=yes -o IdentitiesOnly=yes -i $HOME/.ssh/id_ed25519" "${src[@]}" root@192.168.0.173:/
+1
View File
@@ -27,6 +27,7 @@ cleanup; trap - EXIT
ssh -o BatchMode=yes mac 'test ! -e /etc/sudoers.d/mac-setup && echo "[ok] temp sudoers removed" || echo "[WARN] temp sudoers STILL PRESENT"'
mkdir -p .backup/mac && rsync -a mac:.mac-setup-backup/ .backup/mac/
scripts/authorize-mac-key.sh
[[ ${1:-} == --no-tank ]] && exit 0
PUB=$(ssh mac cat .ssh/id_ed25519.pub)
ssh pve173 "PUB='$PUB' bash -s" < scripts/tank-side.sh
+3
View File
@@ -65,6 +65,9 @@ mkdir -p "$HOME/.ssh"; chmod 700 "$HOME/.ssh"
if [[ -f $HOME/.ssh/id_ed25519 ]]; then log skip "ssh key exists"; else
ssh-keygen -t ed25519 -N '' -C "seth@$HOSTNAME_WANT" -f "$HOME/.ssh/id_ed25519" >/dev/null; log set "generated ~/.ssh/id_ed25519"; CHANGED=1
fi
if [[ -f $HOME/.ssh/id_ed25519_homelab ]]; then log skip "ssh homelab key exists"; else # interactive key; see config/ssh_homelab header
ssh-keygen -t ed25519 -N '' -C "seth@$HOSTNAME_WANT-homelab" -f "$HOME/.ssh/id_ed25519_homelab" >/dev/null; log set "generated ~/.ssh/id_ed25519_homelab"; CHANGED=1
fi
if [[ -f $HOME/.ssh/config ]] && grep -q '^Include ~/mac/config/ssh_homelab' "$HOME/.ssh/config"; then log skip "ssh config include"; else
[[ -f $HOME/.ssh/config ]] && cp "$HOME/.ssh/config" "$BK/ssh_config-$TS"
{ echo 'Include ~/mac/config/ssh_homelab'; [[ -f $HOME/.ssh/config ]] && cat "$HOME/.ssh/config"; } > "$HOME/.ssh/config.new"