Files
saphid--frame-control/scripts/connect.sh
T
saphidandClaude Opus 5.5 a7ae41b94f Verify against a real Frame; switch clipboard to Klipper
The headset desktop is nested Plasma in gamescope with no wl-copy/xclip,
so paste-to-frame.sh now calls Klipper over plasmashell's D-Bus bus.
connect.sh, push.sh, paste-to-frame.sh and install-apps.sh were exercised
on SteamOS 0.3.0 (build 20260922); docs record what was confirmed.
Cross-provider review skipped at Alex's request (Astra quota exhausted).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 19:35:16 +10:00

133 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env zsh
# Mac-side: find the Steam Frame, create a key, add a `Host frame` alias to
# ~/.ssh/config, copy the key, and optionally disable SSH password logins.
#
# Verified on a Frame 2026-09-25 (except --harden). Idempotent: safe to re-run.
#
# Usage:
# scripts/connect.sh [HOST_OR_IP] # set up key + alias
# scripts/connect.sh [HOST_OR_IP] --harden # also disable password auth
#
# Env: FRAME_USER (default steamos), FRAME_ALIAS (default frame).
set -euo pipefail
FRAME_USER=${FRAME_USER:-steamos}
FRAME_ALIAS=${FRAME_ALIAS:-frame}
KEY="$HOME/.ssh/id_ed25519_frame"
CONFIG="$HOME/.ssh/config"
BEGIN_MARK="# >>> steam-frame ($FRAME_ALIAS) >>>"
END_MARK="# <<< steam-frame ($FRAME_ALIAS) <<<"
harden=0
host_arg=""
for arg in "$@"; do
case "$arg" in
--harden) harden=1 ;;
-h|--help) sed -n '2,11p' "$0"; exit 0 ;;
*) host_arg="$arg" ;;
esac
done
port_open() {
# nc resolves through the system resolver (including mDNS for .local).
nc -z -G 3 "$1" 22 >/dev/null 2>&1
}
pick_host() {
local candidates=()
[[ -n "$host_arg" ]] && candidates+=("$host_arg")
candidates+=("$FRAME_ALIAS.local" "$FRAME_ALIAS")
local h
for h in "${candidates[@]}"; do
if port_open "$h"; then
print -r -- "$h"; return 0
fi
print -u2 " - $h: not resolvable or port 22 closed"
done
return 1
}
print "==> Looking for the Steam Frame"
if ! HOST=$(pick_host); then
print -u2 "Could not reach the Frame on port 22."
print -u2 "Check: Developer Mode on + user password set; same Wi-Fi; no client isolation."
print -u2 "Then re-run with the IP from Quick Settings: scripts/connect.sh 192.168.x.y"
exit 1
fi
print " found: $HOST"
print "==> SSH key"
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
if [[ ! -f "$KEY" ]]; then
ssh-keygen -q -t ed25519 -N '' -C "mac->steam-frame" -f "$KEY"
print " created $KEY"
else
print " exists: $KEY"
fi
print "==> ~/.ssh/config alias '$FRAME_ALIAS' -> $HOST"
touch "$CONFIG" && chmod 600 "$CONFIG"
tmp=$(mktemp)
# Drop any previous managed block, then PREPEND a fresh one: ssh uses the first
# value it sees per option, so this block must precede any other "Host frame"
# or "Host *". The trailing "Host *" returns the rest of the file to global scope.
awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
$0==b {skip=1; next}
$0==e {skip=0; next}
!skip {print}
' "$CONFIG" > "$tmp"
{
print -r -- "$BEGIN_MARK"
print -r -- "Host $FRAME_ALIAS"
print -r -- " HostName $HOST"
print -r -- " User $FRAME_USER"
print -r -- " IdentityFile $KEY"
print -r -- " IdentitiesOnly yes"
print -r -- " ServerAliveInterval 30"
print -r -- "Host *"
print -r -- "$END_MARK"
cat "$tmp"
} > "$CONFIG"
rm -f "$tmp"
print "==> Checking key login"
if ssh -o BatchMode=yes -o ConnectTimeout=5 "$FRAME_ALIAS" true 2>/dev/null; then
print " key login already works"
else
print " copying key (enter the Developer Mode password once)"
ssh-copy-id -i "$KEY.pub" -o IdentitiesOnly=yes "$FRAME_USER@$HOST"
ssh -o BatchMode=yes -o ConnectTimeout=5 "$FRAME_ALIAS" true \
|| { print -u2 "Key login still failing after ssh-copy-id."; exit 1; }
print " key login OK"
fi
if (( harden )); then
print "==> Disabling SSH password auth (sudo password asked on the Frame)"
# shellcheck disable=SC2016
if ! ssh -t "$FRAME_ALIAS" '
set -e
grep -Eiq "^[[:space:]]*Include[[:space:]]+/etc/ssh/sshd_config\.d/\*\.conf" /etc/ssh/sshd_config \
|| { echo "sshd_config has no sshd_config.d include; not hardening."; exit 1; }
printf "PasswordAuthentication no\nKbdInteractiveAuthentication no\n" \
| { sudo mkdir -p /etc/ssh/sshd_config.d; sudo tee /etc/ssh/sshd_config.d/01-frame-keys-only.conf >/dev/null; }
sudo sshd -t
sudo systemctl reload sshd
echo "password auth disabled"
'; then
print -u2 "!! Hardening failed. If the drop-in was written, it will disable password SSH"
print -u2 "!! on the next sshd restart. To undo it:"
print -u2 "!! ssh $FRAME_ALIAS 'sudo rm -f /etc/ssh/sshd_config.d/01-frame-keys-only.conf'"
exit 1
fi
if ssh -o BatchMode=yes -o ConnectTimeout=5 "$FRAME_ALIAS" true; then
print " key login still OK after hardening"
else
print -u2 "!! Key login FAILED after hardening. Password SSH is now off."
print -u2 "!! Recover via RDP or 'adb shell' (USB-C), then run:"
print -u2 "!! sudo rm /etc/ssh/sshd_config.d/01-frame-keys-only.conf && sudo systemctl reload sshd"
exit 1
fi
fi
print "\nDone. Try: ssh $FRAME_ALIAS"